summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2018-01-30 22:22:12 +0000
committerVitaly Buka <vitalybuka@google.com>2018-01-30 22:22:12 +0000
commit4ec0d9c1b7e221524a834d9ddfb5f47b36e2ecb8 (patch)
tree702f90bf6e2f2b88c6ad281e76b3a2359b5671cd /compiler-rt
parent5d9844f48aeb3e32fa9526a69bbc36d61acee013 (diff)
downloadbcm5719-llvm-4ec0d9c1b7e221524a834d9ddfb5f47b36e2ecb8.tar.gz
bcm5719-llvm-4ec0d9c1b7e221524a834d9ddfb5f47b36e2ecb8.zip
[sanitizer] Add interceptors for readlinkat, name_to_handle_at, open_by_handle_at
Summary: Also move existing readlink msan interceptor to sanitizer_common. Fixes google/sanitizers#908 Patch by Oliver Chang Reviewers: vitalybuka, eugenis Reviewed By: vitalybuka Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D42630 llvm-svn: 323825
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/msan/msan_interceptors.cc10
-rw-r--r--compiler-rt/lib/msan/tests/msan_test.cc7
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc97
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h6
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h6
-rw-r--r--compiler-rt/test/msan/Linux/name_to_handle_at.cc28
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc20
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/readlinkat.c25
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Posix/readlink.c32
9 files changed, 221 insertions, 10 deletions
diff --git a/compiler-rt/lib/msan/msan_interceptors.cc b/compiler-rt/lib/msan/msan_interceptors.cc
index 02b41efdaca..1084fa8f67c 100644
--- a/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/compiler-rt/lib/msan/msan_interceptors.cc
@@ -138,15 +138,6 @@ INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
#endif
-INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
- ENSURE_MSAN_INITED();
- CHECK_UNPOISONED_STRING(path, 0);
- SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
- if (res > 0)
- __msan_unpoison(buf, res);
- return res;
-}
-
#if !SANITIZER_NETBSD
INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
return (char *)__msan_memcpy(dest, src, n) + n;
@@ -1587,7 +1578,6 @@ void InitializeInterceptors() {
MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
INTERCEPT_FUNCTION(fread);
MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
- INTERCEPT_FUNCTION(readlink);
INTERCEPT_FUNCTION(memccpy);
MSAN_MAYBE_INTERCEPT_MEMPCPY;
INTERCEPT_FUNCTION(bcopy);
diff --git a/compiler-rt/lib/msan/tests/msan_test.cc b/compiler-rt/lib/msan/tests/msan_test.cc
index 074a2f609ed..7a582c935b7 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cc
+++ b/compiler-rt/lib/msan/tests/msan_test.cc
@@ -717,6 +717,13 @@ TEST(MemorySanitizer, readlink) {
delete [] x;
}
+TEST(MemorySanitizer, readlinkat) {
+ char *x = new char[1000];
+ readlinkat(AT_FDCWD, SYMLINK_TO_READ, x, 1000);
+ EXPECT_NOT_POISONED(x[0]);
+ delete[] x;
+}
+
TEST(MemorySanitizer, stat) {
struct stat* st = new struct stat;
int res = stat(FILE_TO_READ, st);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 7aa95458007..14c486a9445 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -6632,6 +6632,98 @@ INTERCEPTOR(int, getgroupmembership, const char *name, u32 basegid, u32 *groups,
#define INIT_GETGROUPLIST
#endif
+#if SANITIZER_INTERCEPT_READLINK
+INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readlink, path, buf, bufsiz);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
+ return res;
+}
+
+#define INIT_READLINK COMMON_INTERCEPT_FUNCTION(readlink)
+#else
+#define INIT_READLINK
+#endif
+
+#if SANITIZER_INTERCEPT_READLINKAT
+INTERCEPTOR(SSIZE_T, readlinkat, int dirfd, const char *path, char *buf,
+ SIZE_T bufsiz) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, readlinkat, dirfd, path, buf, bufsiz);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ SSIZE_T res = REAL(readlinkat)(dirfd, path, buf, bufsiz);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res);
+ return res;
+}
+
+#define INIT_READLINKAT COMMON_INTERCEPT_FUNCTION(readlinkat)
+#else
+#define INIT_READLINKAT
+#endif
+
+#if SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT
+INTERCEPTOR(int, name_to_handle_at, int dirfd, const char *pathname,
+ struct file_handle *handle, int *mount_id, int flags) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, name_to_handle_at, dirfd, pathname, handle,
+ mount_id, flags);
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pathname, REAL(strlen)(pathname) + 1);
+
+ __sanitizer_file_handle *sanitizer_handle =
+ reinterpret_cast<__sanitizer_file_handle*>(handle);
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+
+ int res = REAL(name_to_handle_at)(dirfd, pathname, handle, mount_id, flags);
+ if (!res) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->handle_type,
+ sizeof(sanitizer_handle->handle_type));
+ COMMON_INTERCEPTOR_WRITE_RANGE(
+ ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mount_id, sizeof(*mount_id));
+ }
+ return res;
+}
+
+#define INIT_NAME_TO_HANDLE_AT COMMON_INTERCEPT_FUNCTION(name_to_handle_at)
+#else
+#define INIT_NAME_TO_HANDLE_AT
+#endif
+
+#if SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT
+INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle,
+ int flags) {
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, open_by_handle_at, mount_fd, handle, flags);
+
+ __sanitizer_file_handle *sanitizer_handle =
+ reinterpret_cast<__sanitizer_file_handle*>(handle);
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_bytes,
+ sizeof(sanitizer_handle->handle_bytes));
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->handle_type,
+ sizeof(sanitizer_handle->handle_type));
+ COMMON_INTERCEPTOR_READ_RANGE(
+ ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes);
+
+ return REAL(open_by_handle_at)(mount_fd, handle, flags);
+}
+
+#define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at)
+#else
+#define INIT_OPEN_BY_HANDLE_AT
+#endif
+
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@@ -6852,6 +6944,11 @@ static void InitializeCommonInterceptors() {
INIT_ACCESS;
INIT_FACCESSAT;
INIT_GETGROUPLIST;
+ INIT_READLINK;
+ INIT_READLINKAT;
+
+ INIT_NAME_TO_HANDLE_AT;
+ INIT_OPEN_BY_HANDLE_AT;
#if SANITIZER_NETBSD
COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index cb578624005..42641c0b347 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -442,4 +442,10 @@
#define SANITIZER_INTERCEPT_FACCESSAT SI_NETBSD
#define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD
+#define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX
+#define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX
+
+#define SANITIZER_INTERCEPT_READLINK SI_POSIX
+#define SANITIZER_INTERCEPT_READLINKAT SI_POSIX
+
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
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 9167b3cdef6..2ed8afb2801 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -460,6 +460,12 @@ namespace __sanitizer {
int mnt_freq;
int mnt_passno;
};
+
+ struct __sanitizer_file_handle {
+ unsigned int handle_bytes;
+ int handle_type;
+ unsigned char f_handle[1]; // variable sized
+ };
#endif
#if SANITIZER_MAC || SANITIZER_FREEBSD
diff --git a/compiler-rt/test/msan/Linux/name_to_handle_at.cc b/compiler-rt/test/msan/Linux/name_to_handle_at.cc
new file mode 100644
index 00000000000..0ff8d982f4f
--- /dev/null
+++ b/compiler-rt/test/msan/Linux/name_to_handle_at.cc
@@ -0,0 +1,28 @@
+// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && %run %t
+
+#include <assert.h>
+#include <fcntl.h>
+#include <sanitizer/msan_interface.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(void) {
+ struct file_handle *handle = reinterpret_cast<struct file_handle *>(
+ malloc(sizeof(*handle) + MAX_HANDLE_SZ));
+ handle->handle_bytes = MAX_HANDLE_SZ;
+
+ int mount_id;
+ int res = name_to_handle_at(AT_FDCWD, "/bin/cat", handle, &mount_id, 0);
+ assert(!res);
+ __msan_check_mem_is_initialized(&mount_id, sizeof(mount_id));
+ __msan_check_mem_is_initialized(&handle->handle_bytes,
+ sizeof(handle->handle_bytes));
+ __msan_check_mem_is_initialized(&handle->handle_type,
+ sizeof(handle->handle_type));
+ __msan_check_mem_is_initialized(&handle->f_handle, handle->handle_bytes);
+
+ free(handle);
+ return 0;
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc
new file mode 100644
index 00000000000..79c807848c3
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/name_to_handle_at.cc
@@ -0,0 +1,20 @@
+// RUN: %clangxx -O0 %s -o %t && %run %t
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int main(int argc, char **argv) {
+ int mount_id;
+ struct file_handle *handle = reinterpret_cast<struct file_handle *>(
+ malloc(sizeof(*handle) + MAX_HANDLE_SZ));
+
+ handle->handle_bytes = MAX_HANDLE_SZ;
+ int res = name_to_handle_at(AT_FDCWD, argv[0], handle, &mount_id, 0);
+ assert(!res);
+
+ free(handle);
+ return 0;
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/readlinkat.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/readlinkat.c
new file mode 100644
index 00000000000..9368f986a4e
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/readlinkat.c
@@ -0,0 +1,25 @@
+// RUN: %clang -O0 %s -o %t && %run %t
+
+#include <assert.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ char symlink_path[PATH_MAX];
+ snprintf(symlink_path, sizeof(symlink_path), "%s_%d.symlink", argv[0],
+ getpid());
+ int res = symlink(argv[0], symlink_path);
+ assert(!res);
+
+ char readlinkat_path[PATH_MAX];
+ int res2 = readlinkat(AT_FDCWD, symlink_path, readlinkat_path,
+ sizeof(readlinkat_path));
+ assert(res2 >= 0);
+ readlinkat_path[res2] = '\0';
+ assert(!strcmp(readlinkat_path, argv[0]));
+
+ return 0;
+}
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/readlink.c b/compiler-rt/test/sanitizer_common/TestCases/Posix/readlink.c
new file mode 100644
index 00000000000..d9f39e699a7
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/readlink.c
@@ -0,0 +1,32 @@
+// RUN: %clang -O0 %s -o %t && %run %t
+
+#include <assert.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ char symlink_path[PATH_MAX];
+ snprintf(symlink_path, sizeof(symlink_path), "%s_%d.symlink", argv[0],
+ getpid());
+ int res = symlink(argv[0], symlink_path);
+ assert(!res);
+
+ char readlink_path[PATH_MAX];
+ ssize_t res2 = readlink(symlink_path, readlink_path, sizeof(readlink_path));
+ assert(res2 >= 0);
+ readlink_path[res2] = '\0';
+ assert(!strcmp(readlink_path, argv[0]));
+
+ char readlinkat_path[PATH_MAX];
+ res2 = readlinkat(AT_FDCWD, symlink_path, readlinkat_path,
+ sizeof(readlink_path));
+ assert(res2 >= 0);
+ readlinkat_path[res2] = '\0';
+ assert(!strcmp(readlinkat_path, argv[0]));
+
+ return 0;
+}
OpenPOWER on IntegriCloud