From 2f5fd174c9718701c5c151b796cd4ff4faf1096f Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Fri, 7 Dec 2018 22:01:16 +0000 Subject: [PATCH] Add a new interceptors for statvfs1(2) and fstatvfs1(2) from NetBSD Summary: statvfs1, fstatvfs1 - get file system statistics. While there, use file descriptor related macros in the fstatvfs interceptor. Add a dedicated test. Reviewers: vitalybuka, joerg Reviewed By: vitalybuka Subscribers: dvyukov, kubamracek, mgorny, llvm-commits, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D55031 llvm-svn: 348656 --- .../sanitizer_common_interceptors.inc | 36 +++++++++++- .../sanitizer_platform_interceptors.h | 1 + .../TestCases/NetBSD/statvfs1.cc | 58 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/NetBSD/statvfs1.cc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 46e644e384eb..c7e83924ddb9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -4277,11 +4277,16 @@ INTERCEPTOR(int, statvfs, char *path, void *buf) { INTERCEPTOR(int, fstatvfs, int fd, void *buf) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. int res = REAL(fstatvfs)(fd, buf); - if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); + if (!res) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); + if (fd >= 0) + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); + } return res; } #define INIT_STATVFS \ @@ -7776,6 +7781,34 @@ INTERCEPTOR(char *, fparseln, __sanitizer_FILE *stream, SIZE_T *len, #define INIT_FPARSELN #endif +#if SANITIZER_INTERCEPT_STATVFS1 +INTERCEPTOR(int, statvfs1, const char *path, void *buf, int flags) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, statvfs1, path, buf, flags); + if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1); + int res = REAL(statvfs1)(path, buf, flags); + if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); + return res; +} +INTERCEPTOR(int, fstatvfs1, int fd, void *buf, int flags) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs1, fd, buf, flags); + COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); + int res = REAL(fstatvfs1)(fd, buf, flags); + if (!res) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz); + if (fd >= 0) + COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); + } + return res; +} +#define INIT_STATVFS1 \ + COMMON_INTERCEPT_FUNCTION(statvfs1); \ + COMMON_INTERCEPT_FUNCTION(fstatvfs1); +#else +#define INIT_STATVFS1 +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -8042,6 +8075,7 @@ static void InitializeCommonInterceptors() { INIT_MODCTL; INIT_STRTONUM; INIT_FPARSELN; + INIT_STATVFS1; INIT___PRINTF_CHK; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 28581fb58154..6f9b821fc288 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -531,5 +531,6 @@ #define SANITIZER_INTERCEPT_MODCTL SI_NETBSD #define SANITIZER_INTERCEPT_STRTONUM SI_NETBSD #define SANITIZER_INTERCEPT_FPARSELN SI_NETBSD +#define SANITIZER_INTERCEPT_STATVFS1 SI_NETBSD #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H diff --git a/compiler-rt/test/sanitizer_common/TestCases/NetBSD/statvfs1.cc b/compiler-rt/test/sanitizer_common/TestCases/NetBSD/statvfs1.cc new file mode 100644 index 000000000000..40dfca37bb58 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/NetBSD/statvfs1.cc @@ -0,0 +1,58 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include + +#include + +#include +#include +#include +#include +#include + +void test_statvfs1() { + printf("statvfs1\n"); + + struct statvfs buf; + int rv = statvfs1("/etc/fstab", &buf, ST_WAIT); + assert(rv != -1); + + printf("fstypename='%s'\n", buf.f_fstypename); + printf("mntonname='%s'\n", buf.f_mntonname); + printf("mntfromname='%s'\n", buf.f_mntfromname); +} + +void test_fstatvfs1() { + printf("fstatvfs1\n"); + + int fd = open("/etc/fstab", O_RDONLY); + assert(fd > 0); + + struct statvfs buf; + int rv = fstatvfs1(fd, &buf, ST_WAIT); + assert(rv != -1); + + printf("fstypename='%s'\n", buf.f_fstypename); + printf("mntonname='%s'\n", buf.f_mntonname); + printf("mntfromname='%s'\n", buf.f_mntfromname); + + rv = close(fd); + assert(rv != -1); +} + +int main(void) { + test_statvfs1(); + test_fstatvfs1(); + + // CHECK: statvfs1 + // CHECK: fstypename='{{.*}}' + // CHECK: mntonname='{{.*}}' + // CHECK: mntfromname='{{.*}}' + // CHECK: fstatvfs1 + // CHECK: fstypename='{{.*}}' + // CHECK: mntonname='{{.*}}' + // CHECK: mntfromname='{{.*}}' + + return 0; +}