[compiler-rt] r200464 - [msan] Intercept *getxattr and *listxattr.

Sergey Matveev earthdok at google.com
Thu Jan 30 04:21:13 PST 2014


Author: smatveev
Date: Thu Jan 30 06:21:12 2014
New Revision: 200464

URL: http://llvm.org/viewvc/llvm-project?rev=200464&view=rev
Log:
[msan] Intercept *getxattr and *listxattr.

Added:
    compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr.cc
    compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr_test_root/
    compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr_test_root/a
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_syscalls.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h

Added: compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr.cc?rev=200464&view=auto
==============================================================================
--- compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr.cc (added)
+++ compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr.cc Thu Jan 30 06:21:12 2014
@@ -0,0 +1,142 @@
+// RUN: %clangxx_msan -m64 -O0 %s -o %t && %t %p 2>&1
+// RUN: %clangxx_msan -m64 -O0 -D_FILE_OFFSET_BITS=64 %s -o %t && %t %p 2>&1
+// RUN: %clangxx_msan -m64 -O3 %s -o %t && %t %p 2>&1
+
+#include <argz.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sanitizer/msan_interface.h>
+
+// Do not depend on libattr headers.
+#ifndef ENOATTR
+#define ENOATTR ENODATA
+#endif
+
+extern "C" {
+ssize_t listxattr(const char *path, char *list, size_t size);
+ssize_t llistxattr(const char *path, char *list, size_t size);
+ssize_t flistxattr(int fd, char *list, size_t size);
+ssize_t getxattr(const char *path, const char *name, void *value, size_t size);
+ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size);
+ssize_t fgetxattr(int fd, const char *name, void *value, size_t size);
+}
+
+char g_path[1024];
+int g_fd;
+
+// Life before closures...
+ssize_t listxattr_wrapper(char *buf, size_t size) {
+  return listxattr(g_path, buf, size);
+}
+
+ssize_t llistxattr_wrapper(char *buf, size_t size) {
+  return llistxattr(g_path, buf, size);
+}
+
+ssize_t flistxattr_wrapper(char *buf, size_t size) {
+  return flistxattr(g_fd, buf, size);
+}
+
+ssize_t getxattr_wrapper(const char *name, char *buf, size_t size) {
+  return getxattr(g_path, name, buf, size);
+}
+
+ssize_t lgetxattr_wrapper(const char *name, char *buf, size_t size) {
+  return lgetxattr(g_path, name, buf, size);
+}
+
+ssize_t fgetxattr_wrapper(const char *name, char *buf, size_t size) {
+  return fgetxattr(g_fd, name, buf, size);
+}
+
+size_t test_list(ssize_t fun(char*, size_t), char **buf) {
+  int buf_size = 1024;
+  while (true) {
+    *buf = (char *)malloc(buf_size);
+    assert(__msan_test_shadow(*buf, buf_size) != -1);
+    ssize_t res = fun(*buf, buf_size);
+    if (res >= 0) {
+      assert(__msan_test_shadow(*buf, buf_size) == res);
+      return res;
+    }
+    if (errno == ENOTSUP) {
+      printf("Extended attributes are disabled. *xattr test is a no-op.\n");
+      exit(0);
+    }
+    assert(errno == ERANGE);
+    free(*buf);
+    buf_size *= 2;
+  }
+}
+
+// True means success. False means result inconclusive because we don't have
+// access to this attribute.
+bool test_get_single_attr(ssize_t fun(const char *, char *, size_t),
+                          const char *attr_name) {
+  char *buf;
+  int buf_size = 1024;
+  while (true) {
+    buf = (char *)malloc(buf_size);
+    assert(__msan_test_shadow(buf, buf_size) != -1);
+    ssize_t res = fun(attr_name, buf, buf_size);
+    if (res >= 0) {
+      assert(__msan_test_shadow(buf, buf_size) == res);
+      free(buf);
+      return true;
+    }
+    if (errno == ENOTSUP) {
+      printf("Extended attributes are disabled. *xattr test is a no-op.\n");
+      exit(0);
+    }
+    if (errno == ENOATTR)
+      return false;
+    assert(errno == ERANGE);
+    free(buf);
+    buf_size *= 2;
+  }
+}
+
+void test_get(ssize_t fun(const char *, char *, size_t), const char *attr_list,
+              size_t attr_list_size) {
+  // Try every attribute, until we see one we can access. Attribute names are
+  // null-separated strings in attr_list.
+  size_t attr_list_len = argz_count(attr_list, attr_list_size);
+  char **attrs = (char **)malloc((attr_list_len + 1) * sizeof(char *));
+  size_t i;
+  for (i = 0; (i < attr_list_len) && attrs[i]; i++) {
+    if (test_get_single_attr(fun, attrs[i]))
+      return;
+  }
+  printf("*xattr test could not access any attributes.\n");
+}
+
+// TODO: set some attributes before trying to retrieve them with *getxattr.
+// Currently the list is empty, so *getxattr is not tested.
+int main(int argc, char *argv[]) {
+  assert(argc == 2);
+  snprintf(g_path, sizeof(g_path), "%s/%s", argv[1], "xattr_test_root/a");
+
+  g_fd = open(g_path, O_RDONLY);
+  assert(g_fd);
+
+  char *attr_list;
+  size_t attr_list_size;
+  attr_list_size = test_list(listxattr_wrapper, &attr_list);
+  free(attr_list);
+  attr_list_size = test_list(llistxattr_wrapper, &attr_list);
+  free(attr_list);
+  attr_list_size = test_list(flistxattr_wrapper, &attr_list);
+
+  test_get(getxattr_wrapper, attr_list, attr_list_size);
+  test_get(lgetxattr_wrapper, attr_list, attr_list_size);
+  test_get(fgetxattr_wrapper, attr_list, attr_list_size);
+
+  free(attr_list);
+  return 0;
+}

Added: compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr_test_root/a
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/lit_tests/Linux/xattr_test_root/a?rev=200464&view=auto
==============================================================================
    (empty)

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=200464&r1=200463&r2=200464&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Jan 30 06:21:12 2014
@@ -3081,6 +3081,79 @@ INTERCEPTOR(void *, __tls_get_addr, void
 #define INIT_TLS_GET_ADDR
 #endif
 
+#if SANITIZER_INTERCEPT_LISTXATTR
+INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
+  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+  SSIZE_T res = REAL(listxattr)(path, list, size);
+  // Here and below, size == 0 is a special case where nothing is written to the
+  // buffer, and res contains the desired buffer size.
+  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+  return res;
+}
+INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
+  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+  SSIZE_T res = REAL(llistxattr)(path, list, size);
+  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+  return res;
+}
+INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
+  SSIZE_T res = REAL(flistxattr)(fd, list, size);
+  if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
+  return res;
+}
+#define INIT_LISTXATTR                   \
+  COMMON_INTERCEPT_FUNCTION(listxattr);  \
+  COMMON_INTERCEPT_FUNCTION(llistxattr); \
+  COMMON_INTERCEPT_FUNCTION(flistxattr);
+#else
+#define INIT_LISTXATTR
+#endif
+
+#if SANITIZER_INTERCEPT_GETXATTR
+INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
+            SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
+  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+  SSIZE_T res = REAL(getxattr)(path, name, value, size);
+  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+  return res;
+}
+INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
+            SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
+  if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
+  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+  SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
+  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+  return res;
+}
+INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
+            SIZE_T size) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
+  if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
+  SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
+  if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
+  return res;
+}
+#define INIT_GETXATTR                   \
+  COMMON_INTERCEPT_FUNCTION(getxattr);  \
+  COMMON_INTERCEPT_FUNCTION(lgetxattr); \
+  COMMON_INTERCEPT_FUNCTION(fgetxattr);
+#else
+#define INIT_GETXATTR
+#endif
+
+
 #define SANITIZER_COMMON_INTERCEPTORS_INIT \
   INIT_TEXTDOMAIN;                         \
   INIT_STRCMP;                             \
@@ -3197,4 +3270,6 @@ INTERCEPTOR(void *, __tls_get_addr, void
   INIT_ICONV;                              \
   INIT_TIMES;                              \
   INIT_TLS_GET_ADDR;                       \
+  INIT_LISTXATTR;                          \
+  INIT_GETXATTR;
 /**/

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_syscalls.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_syscalls.inc?rev=200464&r1=200463&r2=200464&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_syscalls.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_syscalls.inc Thu Jan 30 06:21:12 2014
@@ -1004,8 +1004,8 @@ PRE_SYSCALL(getxattr)(const void *path,
 
 POST_SYSCALL(getxattr)(long res, const void *path, const void *name,
                        void *value, long size) {
-  if (res >= 0) {
-    if (value) POST_WRITE(value, size);
+  if (size && res > 0) {
+    if (value) POST_WRITE(value, res);
   }
 }
 
@@ -1019,8 +1019,8 @@ PRE_SYSCALL(lgetxattr)(const void *path,
 
 POST_SYSCALL(lgetxattr)(long res, const void *path, const void *name,
                         void *value, long size) {
-  if (res >= 0) {
-    if (value) POST_WRITE(value, size);
+  if (size && res > 0) {
+    if (value) POST_WRITE(value, res);
   }
 }
 
@@ -1031,8 +1031,8 @@ PRE_SYSCALL(fgetxattr)(long fd, const vo
 
 POST_SYSCALL(fgetxattr)(long res, long fd, const void *name, void *value,
                         long size) {
-  if (res >= 0) {
-    if (value) POST_WRITE(value, size);
+  if (size && res > 0) {
+    if (value) POST_WRITE(value, res);
   }
 }
 
@@ -1042,8 +1042,8 @@ PRE_SYSCALL(listxattr)(const void *path,
 }
 
 POST_SYSCALL(listxattr)(long res, const void *path, void *list, long size) {
-  if (res >= 0) {
-    if (list) POST_WRITE(list, size);
+  if (size && res > 0) {
+    if (list) POST_WRITE(list, res);
   }
 }
 
@@ -1053,16 +1053,16 @@ PRE_SYSCALL(llistxattr)(const void *path
 }
 
 POST_SYSCALL(llistxattr)(long res, const void *path, void *list, long size) {
-  if (res >= 0) {
-    if (list) POST_WRITE(list, size);
+  if (size && res > 0) {
+    if (list) POST_WRITE(list, res);
   }
 }
 
 PRE_SYSCALL(flistxattr)(long fd, void *list, long size) {}
 
 POST_SYSCALL(flistxattr)(long res, long fd, void *list, long size) {
-  if (res >= 0) {
-    if (list) POST_WRITE(list, size);
+  if (size && res > 0) {
+    if (list) POST_WRITE(list, res);
   }
 }
 

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=200464&r1=200463&r2=200464&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Thu Jan 30 06:21:12 2014
@@ -179,4 +179,7 @@
 
 #define SANITIZER_INTERCEPT_TLS_GET_ADDR SI_LINUX_NOT_ANDROID
 
+#define SANITIZER_INTERCEPT_LISTXATTR SI_LINUX
+#define SANITIZER_INTERCEPT_GETXATTR SI_LINUX
+
 #endif  // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H





More information about the llvm-commits mailing list