[Sanitizer] intercept part of sysctl Api
authorDavid Carlier <devnexen@gmail.com>
Tue, 4 Dec 2018 19:00:38 +0000 (19:00 +0000)
committerDavid Carlier <devnexen@gmail.com>
Tue, 4 Dec 2018 19:00:38 +0000 (19:00 +0000)
- Distringuish what FreeBSD/NetBSD can and NetBSD specifics.
- Fixing page size value collection.

Reviewers: krytarowski, vitalybuka

Reviewed By: krytarowski

Differential Revision: https://reviews.llvm.org/D55265

llvm-svn: 348293

compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
compiler-rt/test/sanitizer_common/TestCases/Posix/sysctl.cc [moved from compiler-rt/test/sanitizer_common/TestCases/NetBSD/sysctl.cc with 91% similarity]

index c4f3296..ea97c78 100644 (file)
@@ -7568,36 +7568,6 @@ INTERCEPTOR(int, sysctlbyname, char *sname, void *oldp, SIZE_T *oldlenp,
   return res;
 }
 
-INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
-            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
-            int v) {
-  void *ctx;
-  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
-                           csz, rnode, v);
-  if (sname)
-    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
-  if (namelenp)
-    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
-  if (csz)
-    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
-  // Skip rnode, it's rarely used and not trivial to sanitize
-  // It's also used mostly internally
-  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
-  if (!res) {
-    if (namelenp) {
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
-      if (name)
-        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
-    }
-    if (csz) {
-      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
-      if (cname)
-        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
-    }
-  }
-  return res;
-}
-
 INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
             SIZE_T *namelenp) {
   void *ctx;
@@ -7617,6 +7587,15 @@ INTERCEPTOR(int, sysctlnametomib, const char *sname, int *name,
   return res;
 }
 
+#define INIT_SYSCTL                        \
+  COMMON_INTERCEPT_FUNCTION(sysctl);       \
+  COMMON_INTERCEPT_FUNCTION(sysctlbyname); \
+  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);
+#else
+#define INIT_SYSCTL
+#endif
+
+#if SANITIZER_INTERCEPT_ASYSCTL
 INTERCEPTOR(void *, asysctl, const int *name, SIZE_T namelen, SIZE_T *len) {
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, asysctl, name, namelen, len);
@@ -7642,17 +7621,50 @@ INTERCEPTOR(void *, asysctlbyname, const char *sname, SIZE_T *len) {
   }
   return res;
 }
-#define INIT_SYSCTL                                                            \
-  COMMON_INTERCEPT_FUNCTION(sysctl);                                           \
-  COMMON_INTERCEPT_FUNCTION(sysctlbyname);                                     \
-  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);                                 \
-  COMMON_INTERCEPT_FUNCTION(sysctlnametomib);                                  \
-  COMMON_INTERCEPT_FUNCTION(asysctl);                                          \
+#define INIT_ASYSCTL                           \
+  COMMON_INTERCEPT_FUNCTION(asysctl);          \
   COMMON_INTERCEPT_FUNCTION(asysctlbyname);
 #else
-#define INIT_SYSCTL
+#define INIT_ASYSCTL
+#endif
+
+#if SANITIZER_INTERCEPT_SYSCTLGETMIBINFO
+INTERCEPTOR(int, sysctlgetmibinfo, char *sname, int *name,
+            unsigned int *namelenp, char *cname, SIZE_T *csz, void **rnode,
+            int v) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, sysctlgetmibinfo, sname, name, namelenp, cname,
+                           csz, rnode, v);
+  if (sname)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, sname, REAL(strlen)(sname) + 1);
+  if (namelenp)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, namelenp, sizeof(*namelenp));
+  if (csz)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, csz, sizeof(*csz));
+  // Skip rnode, it's rarely used and not trivial to sanitize
+  // It's also used mostly internally
+  int res = REAL(sysctlgetmibinfo)(sname, name, namelenp, cname, csz, rnode, v);
+  if (!res) {
+    if (namelenp) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelenp, sizeof(*namelenp));
+      if (name)
+        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, *namelenp * sizeof(*name));
+    }
+    if (csz) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, csz, sizeof(*csz));
+      if (cname)
+        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cname, *csz);
+    }
+  }
+  return res;
+}
+#define INIT_SYSCTLGETMIBINFO                  \
+  COMMON_INTERCEPT_FUNCTION(sysctlgetmibinfo);
+#else
+#define INIT_SYSCTLGETMIBINFO
 #endif
 
+
 static void InitializeCommonInterceptors() {
   static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
   interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
@@ -7913,6 +7925,8 @@ static void InitializeCommonInterceptors() {
   INIT_REGEX;
   INIT_FTS;
   INIT_SYSCTL;
+  INIT_ASYSCTL;
+  INIT_SYSCTLGETMIBINFO;
 
   INIT___PRINTF_CHK;
 }
index aff9a6f..d2234bb 100644 (file)
@@ -772,7 +772,7 @@ int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
   return sysctl(name, namelen, oldp, (size_t *)oldlenp, (void *)newp,
                 (size_t)newlen);
 #else
-  return sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
+  return internal_syscall(SYSCALL(__sysctl), name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen);
 #endif
 }
 
@@ -1076,6 +1076,14 @@ uptr GetPageSize() {
   return EXEC_PAGESIZE;
 #elif SANITIZER_USE_GETAUXVAL
   return getauxval(AT_PAGESZ);
+#elif SANITIZER_FREEBSD || SANITIZER_NETBSD
+// Use sysctl as sysconf can trigger interceptors internally.
+  int pz = 0;
+  uptr pzl = sizeof(pz);
+  int mib[2] = {CTL_HW, HW_PAGESIZE};
+  int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0);
+  CHECK_EQ(rv, 0);
+  return (uptr)pz;
 #else
   return sysconf(_SC_PAGESIZE);  // EXEC_PAGESIZE may not be trustworthy.
 #endif
index f27145d..03a0cc0 100644 (file)
 #define SANITIZER_INTERCEPT_GETVFSSTAT SI_NETBSD
 #define SANITIZER_INTERCEPT_REGEX SI_NETBSD
 #define SANITIZER_INTERCEPT_FTS SI_NETBSD
-#define SANITIZER_INTERCEPT_SYSCTL SI_NETBSD
+#define SANITIZER_INTERCEPT_SYSCTL (SI_NETBSD || SI_FREEBSD)
+#define SANITIZER_INTERCEPT_ASYSCTL SI_NETBSD
+#define SANITIZER_INTERCEPT_SYSCTLGETMIBINFO SI_NETBSD
 
 #endif  // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
@@ -1,4 +1,6 @@
 // RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s
+//
+// UNSUPPORTED: linux darwin solaris
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -9,6 +11,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifndef __arraycount
+#define __arraycount(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
 void test_sysctl() {
   char buf[100];
   size_t len = sizeof(buf);
@@ -22,28 +28,12 @@ void test_sysctl() {
 void test_sysctlbyname() {
   char buf[100];
   size_t len = sizeof(buf);
-  int mib[] = {CTL_KERN, KERN_OSTYPE};
   int rv = sysctlbyname("kern.ostype", buf, &len, NULL, 0);
   assert(!rv);
 
   printf("sysctlbyname: '%s' size: '%zu'\n", buf, len);
 }
 
-void test_sysctlgetmibinfo() {
-  int mib[CTL_MAXNAME];
-  unsigned int mib_len = __arraycount(mib);
-  int rv = sysctlgetmibinfo("kern.ostype", &mib[0], &mib_len, NULL, NULL, NULL,
-                       SYSCTL_VERSION);
-  assert(!rv);
-
-  char buf[100];
-  size_t len = sizeof(buf);
-  rv = sysctl(mib, mib_len, buf, &len, NULL, 0);
-  assert(!rv);
-
-  printf("sysctlgetmibinfo: '%s' size: '%zu'\n", buf, len);
-}
-
 void test_sysctlnametomib() {
   int mib[CTL_MAXNAME];
   size_t mib_len = __arraycount(mib);
@@ -58,6 +48,7 @@ void test_sysctlnametomib() {
   printf("sysctlnametomib: '%s' size: '%zu'\n", buf, len);
 }
 
+#if defined(__NetBSD__)
 void test_asysctl() {
   int mib[] = {CTL_KERN, KERN_OSTYPE};
   size_t len;
@@ -79,23 +70,43 @@ void test_asysctlbyname() {
   free(buf);
 }
 
+void test_sysctlgetmibinfo() {
+  int mib[CTL_MAXNAME];
+  unsigned int mib_len = __arraycount(mib);
+  int rv = sysctlgetmibinfo("kern.ostype", &mib[0], &mib_len, NULL, NULL, NULL,
+                       SYSCTL_VERSION);
+  assert(!rv);
+
+  char buf[100];
+  size_t len = sizeof(buf);
+  rv = sysctl(mib, mib_len, buf, &len, NULL, 0);
+  assert(!rv);
+
+  printf("sysctlgetmibinfo: '%s' size: '%zu'\n", buf, len);
+}
+#endif
+
 int main(void) {
   printf("sysctl\n");
 
   test_sysctl();
   test_sysctlbyname();
-  test_sysctlgetmibinfo();
   test_sysctlnametomib();
+#if defined(__NetBSD__)
   test_asysctl();
   test_asysctlbyname();
+  test_sysctlgetmibinfo();
+#endif
 
   // CHECK: sysctl
   // CHECK: sysctl: '{{.*}}' size: '{{.*}}'
   // CHECK: sysctlbyname: '{{.*}}' size: '{{.*}}'
-  // CHECK: sysctlgetmibinfo: '{{.*}}' size: '{{.*}}'
   // CHECK: sysctlnametomib: '{{.*}}' size: '{{.*}}'
+#if defined(__NetBSD__)
   // CHECK: asysctl: '{{.*}}' size: '{{.*}}'
   // CHECK: asysctlbyname: '{{.*}}' size: '{{.*}}'
+  // CHECK: sysctlgetmibinfo: '{{.*}}' size: '{{.*}}'
+#endif
 
   return 0;
 }