summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Gorny <mgorny@gentoo.org>2019-01-02 17:37:09 +0000
committerMichal Gorny <mgorny@gentoo.org>2019-01-02 17:37:09 +0000
commit1ee32a1d24df667522ea2a2bd89930a2b8991eca (patch)
treeeca5b22c11e34795365ce5688d70034e39404183
parent8b9ea8fbdca692b1c92c15c6778f9ada59697a82 (diff)
downloadcompiler-rt-1ee32a1d24df667522ea2a2bd89930a2b8991eca.tar.gz
[sanitizer_common] Implement popen, popenve, pclose interceptors
Implement the interceptors for popen(), pclose() and popenve() functions. The first two are POSIX, the third one is specific to NetBSD. popen() spawns a process and creates a FILE object piping data from/to that process. pclose() closes the pipe and waits for the process to terminate appropriately. For the purpose of popen(), the COMMON_INTERCEPTOR_FILE_OPEN macro is modified to allow null path parameter. Differential Revision: https://reviews.llvm.org/D56157 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@350232 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc74
-rw-r--r--lib/sanitizer_common/sanitizer_platform_interceptors.h4
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc3
3 files changed, 80 insertions, 1 deletions
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index bf6dfd1a7..f1e4c38a6 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -9116,6 +9116,77 @@ INTERCEPTOR(void, arc4random_addrandom, u8 *dat, int datlen) {
#define INIT_ARC4RANDOM
#endif
+#if SANITIZER_INTERCEPT_POPEN
+INTERCEPTOR(__sanitizer_FILE *, popen, const char *command, const char *type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, popen, command, type);
+ if (command)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, command, REAL(strlen)(command) + 1);
+ if (type)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
+ __sanitizer_FILE *res = REAL(popen)(command, type);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_POPEN COMMON_INTERCEPT_FUNCTION(popen)
+#else
+#define INIT_POPEN
+#endif
+
+#if SANITIZER_INTERCEPT_POPENVE
+INTERCEPTOR(__sanitizer_FILE *, popenve, const char *path,
+ char *const *argv, char *const *envp, const char *type) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, popenve, path, argv, envp, type);
+ if (path)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+ if (argv) {
+ for (char *const *pa = argv; ; ++pa) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
+ if (!*pa)
+ break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
+ }
+ }
+ if (envp) {
+ for (char *const *pa = envp; ; ++pa) {
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, pa, sizeof(char **));
+ if (!*pa)
+ break;
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, *pa, REAL(strlen)(*pa) + 1);
+ }
+ }
+ if (type)
+ COMMON_INTERCEPTOR_READ_RANGE(ctx, type, REAL(strlen)(type) + 1);
+ __sanitizer_FILE *res = REAL(popenve)(path, argv, envp, type);
+ COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, nullptr);
+ if (res) unpoison_file(res);
+ return res;
+}
+#define INIT_POPENVE COMMON_INTERCEPT_FUNCTION(popenve)
+#else
+#define INIT_POPENVE
+#endif
+
+#if SANITIZER_INTERCEPT_PCLOSE
+INTERCEPTOR(int, pclose, __sanitizer_FILE *fp) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, pclose, fp);
+ COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
+ const FileMetadata *m = GetInterceptorMetadata(fp);
+ int res = REAL(pclose)(fp);
+ if (m) {
+ COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
+ DeleteInterceptorMetadata(fp);
+ }
+ return res;
+}
+#define INIT_PCLOSE COMMON_INTERCEPT_FUNCTION(pclose);
+#else
+#define INIT_PCLOSE
+#endif
+
static void InitializeCommonInterceptors() {
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
interceptor_metadata_map =
@@ -9398,6 +9469,9 @@ static void InitializeCommonInterceptors() {
INIT_CDB;
INIT_GETFSENT;
INIT_ARC4RANDOM;
+ INIT_POPEN;
+ INIT_POPENVE;
+ INIT_PCLOSE;
INIT___PRINTF_CHK;
}
diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h
index a7a3ce2bd..04fc4f06a 100644
--- a/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -548,4 +548,8 @@
#define SANITIZER_INTERCEPT_GETFSENT (SI_FREEBSD || SI_NETBSD || SI_MAC)
#define SANITIZER_INTERCEPT_ARC4RANDOM (SI_FREEBSD || SI_NETBSD)
+#define SANITIZER_INTERCEPT_POPEN SI_POSIX
+#define SANITIZER_INTERCEPT_POPENVE SI_NETBSD
+#define SANITIZER_INTERCEPT_PCLOSE SI_POSIX
+
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index cc6dab8f1..eaf845588 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -2254,7 +2254,8 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
(void) ctx;
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) \
- Acquire(thr, pc, File2addr(path)); \
+ if (path) \
+ Acquire(thr, pc, File2addr(path)); \
if (file) { \
int fd = fileno_unlocked(file); \
if (fd >= 0) FdFileCreate(thr, pc, fd); \