[compiler-rt] 1fe0420 - [dfsan] Add origin ABI wrappers

Jianzhou Zhao via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 19 09:23:48 PDT 2021


Author: Jianzhou Zhao
Date: 2021-03-19T16:23:25Z
New Revision: 1fe042041c451760437d3e4285820f4581f0b744

URL: https://github.com/llvm/llvm-project/commit/1fe042041c451760437d3e4285820f4581f0b744
DIFF: https://github.com/llvm/llvm-project/commit/1fe042041c451760437d3e4285820f4581f0b744.diff

LOG: [dfsan] Add origin ABI wrappers

supported: dl_get_tls_static_info, calloc, clock_gettime,
dfsan_set_write_callback, dl_iterato_phdr, dlopen, memcpy,
memmove, memset, pread, read, strcat, strdup, strncpy

This is a part of https://reviews.llvm.org/D95835.

Reviewed By: morehouse

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

Added: 
    

Modified: 
    compiler-rt/lib/dfsan/dfsan.cpp
    compiler-rt/lib/dfsan/dfsan.h
    compiler-rt/lib/dfsan/dfsan_custom.cpp
    compiler-rt/test/dfsan/custom.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index 5a9620aa417e..2aff8869d2cf 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -736,6 +736,13 @@ dfsan_read_origin_of_first_taint(const void *addr, uptr size) {
   return GetOriginIfTainted((uptr)addr, size);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label_origin(dfsan_label label,
+                                                          dfsan_origin origin,
+                                                          void *addr,
+                                                          uptr size) {
+  __dfsan_set_label(label, origin, addr, size);
+}
+
 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
 const struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) {
   return &__dfsan_label_info[label];

diff  --git a/compiler-rt/lib/dfsan/dfsan.h b/compiler-rt/lib/dfsan/dfsan.h
index c2f173f079ff..73b4e4dcd297 100644
--- a/compiler-rt/lib/dfsan/dfsan.h
+++ b/compiler-rt/lib/dfsan/dfsan.h
@@ -48,6 +48,10 @@ void dfsan_clear_thread_local_state();
 // from the address addr.
 dfsan_origin dfsan_read_origin_of_first_taint(const void *addr, uptr size);
 
+// Set the data within [addr, addr+size) with label and origin.
+void dfsan_set_label_origin(dfsan_label label, dfsan_origin origin, void *addr,
+                            uptr size);
+
 // Copy or move the origins of the len bytes from src to dst.
 void dfsan_mem_origin_transfer(const void *dst, const void *src, uptr len);
 }  // extern "C"

diff  --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp
index 804c57bd3c35..96b7668db90c 100644
--- a/compiler-rt/lib/dfsan/dfsan_custom.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp
@@ -470,6 +470,15 @@ SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_calloc(size_t nmemb, size_t size,
   return p;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_calloc(
+    size_t nmemb, size_t size, dfsan_label nmemb_label, dfsan_label size_label,
+    dfsan_label *ret_label, dfsan_origin nmemb_origin, dfsan_origin size_origin,
+    dfsan_origin *ret_origin) {
+  void *p = __dfsw_calloc(nmemb, size, nmemb_label, size_label, ret_label);
+  *ret_origin = 0;
+  return p;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE size_t
 __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
   size_t ret = strlen(s);
@@ -499,6 +508,11 @@ static void *dfsan_memmove(void *dest, const void *src, size_t n) {
   return internal_memmove(dest, src, n);
 }
 
+static void *dfsan_memmove_with_origin(void *dest, const void *src, size_t n) {
+  dfsan_mem_origin_transfer(dest, src, n);
+  return dfsan_memmove(dest, src, n);
+}
+
 static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
   dfsan_label *sdest = shadow_for(dest);
   const dfsan_label *ssrc = shadow_for(src);
@@ -506,11 +520,22 @@ static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
   return internal_memcpy(dest, src, n);
 }
 
+static void *dfsan_memcpy_with_origin(void *dest, const void *src, size_t n) {
+  dfsan_mem_origin_transfer(dest, src, n);
+  return dfsan_memcpy(dest, src, n);
+}
+
 static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) {
   internal_memset(s, c, n);
   dfsan_set_label(c_label, s, n);
 }
 
+static void dfsan_memset_with_origin(void *s, int c, dfsan_label c_label,
+                                     dfsan_origin c_origin, size_t n) {
+  internal_memset(s, c, n);
+  dfsan_set_label_origin(c_label, c_origin, s, n);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void *__dfsw_memcpy(void *dest, const void *src, size_t n,
                     dfsan_label dest_label, dfsan_label src_label,
@@ -519,6 +544,17 @@ void *__dfsw_memcpy(void *dest, const void *src, size_t n,
   return dfsan_memcpy(dest, src, n);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memcpy(void *dest, const void *src, size_t n,
+                    dfsan_label dest_label, dfsan_label src_label,
+                    dfsan_label n_label, dfsan_label *ret_label,
+                    dfsan_origin dest_origin, dfsan_origin src_origin,
+                    dfsan_origin n_origin, dfsan_origin *ret_origin) {
+  *ret_label = dest_label;
+  *ret_origin = dest_origin;
+  return dfsan_memcpy_with_origin(dest, src, n);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void *__dfsw_memmove(void *dest, const void *src, size_t n,
                      dfsan_label dest_label, dfsan_label src_label,
@@ -527,6 +563,17 @@ void *__dfsw_memmove(void *dest, const void *src, size_t n,
   return dfsan_memmove(dest, src, n);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memmove(void *dest, const void *src, size_t n,
+                     dfsan_label dest_label, dfsan_label src_label,
+                     dfsan_label n_label, dfsan_label *ret_label,
+                     dfsan_origin dest_origin, dfsan_origin src_origin,
+                     dfsan_origin n_origin, dfsan_origin *ret_origin) {
+  *ret_label = dest_label;
+  *ret_origin = dest_origin;
+  return dfsan_memmove_with_origin(dest, src, n);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE
 void *__dfsw_memset(void *s, int c, size_t n,
                     dfsan_label s_label, dfsan_label c_label,
@@ -536,6 +583,18 @@ void *__dfsw_memset(void *s, int c, size_t n,
   return s;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE
+void *__dfso_memset(void *s, int c, size_t n, dfsan_label s_label,
+                    dfsan_label c_label, dfsan_label n_label,
+                    dfsan_label *ret_label, dfsan_origin s_origin,
+                    dfsan_origin c_origin, dfsan_origin n_origin,
+                    dfsan_origin *ret_origin) {
+  dfsan_memset_with_origin(s, c, c_label, c_origin, n);
+  *ret_label = s_label;
+  *ret_origin = s_origin;
+  return s;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
                                                   dfsan_label dest_label,
                                                   dfsan_label src_label,
@@ -550,6 +609,23 @@ SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src,
   return ret;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
+    char *dest, const char *src, dfsan_label dest_label, dfsan_label src_label,
+    dfsan_label *ret_label, dfsan_origin dest_origin, dfsan_origin src_origin,
+    dfsan_origin *ret_origin) {
+  size_t dest_len = strlen(dest);
+  char *ret = strcat(dest, src);  // NOLINT
+  dfsan_label *sdest = shadow_for(dest + dest_len);
+  const dfsan_label *ssrc = shadow_for(src);
+  size_t src_len = strlen(src);
+  dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
+  internal_memcpy((void *)sdest, (const void *)ssrc,
+                  src_len * sizeof(dfsan_label));
+  *ret_label = dest_label;
+  *ret_origin = dest_origin;
+  return ret;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE char *
 __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
   size_t len = strlen(s);
@@ -559,6 +635,19 @@ __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
   return static_cast<char *>(p);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strdup(const char *s,
+                                                  dfsan_label s_label,
+                                                  dfsan_label *ret_label,
+                                                  dfsan_origin s_origin,
+                                                  dfsan_origin *ret_origin) {
+  size_t len = strlen(s);
+  void *p = malloc(len + 1);
+  dfsan_memcpy_with_origin(p, s, len + 1);
+  *ret_label = 0;
+  *ret_origin = 0;
+  return static_cast<char *>(p);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE char *
 __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
                dfsan_label s2_label, dfsan_label n_label,
@@ -575,6 +664,24 @@ __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label,
   return s1;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncpy(
+    char *s1, const char *s2, size_t n, dfsan_label s1_label,
+    dfsan_label s2_label, dfsan_label n_label, dfsan_label *ret_label,
+    dfsan_origin s1_origin, dfsan_origin s2_origin, dfsan_origin n_origin,
+    dfsan_origin *ret_origin) {
+  size_t len = strlen(s2);
+  if (len < n) {
+    dfsan_memcpy_with_origin(s1, s2, len + 1);
+    dfsan_memset_with_origin(s1 + len + 1, 0, 0, 0, n - len - 1);
+  } else {
+    dfsan_memcpy_with_origin(s1, s2, n);
+  }
+
+  *ret_label = s1_label;
+  *ret_origin = s1_origin;
+  return s1;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
 __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
              dfsan_label fd_label, dfsan_label buf_label,
@@ -587,6 +694,17 @@ __dfsw_pread(int fd, void *buf, size_t count, off_t offset,
   return ret;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_pread(
+    int fd, void *buf, size_t count, off_t offset, dfsan_label fd_label,
+    dfsan_label buf_label, dfsan_label count_label, dfsan_label offset_label,
+    dfsan_label *ret_label, dfsan_origin fd_origin, dfsan_origin buf_origin,
+    dfsan_origin count_origin, dfsan_label offset_origin,
+    dfsan_origin *ret_origin) {
+  ssize_t ret = __dfsw_pread(fd, buf, count, offset, fd_label, buf_label,
+                             count_label, offset_label, ret_label);
+  return ret;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE ssize_t
 __dfsw_read(int fd, void *buf, size_t count,
              dfsan_label fd_label, dfsan_label buf_label,
@@ -599,6 +717,16 @@ __dfsw_read(int fd, void *buf, size_t count,
   return ret;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_read(
+    int fd, void *buf, size_t count, dfsan_label fd_label,
+    dfsan_label buf_label, dfsan_label count_label, dfsan_label *ret_label,
+    dfsan_origin fd_origin, dfsan_origin buf_origin, dfsan_origin count_origin,
+    dfsan_origin *ret_origin) {
+  ssize_t ret =
+      __dfsw_read(fd, buf, count, fd_label, buf_label, count_label, ret_label);
+  return ret;
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
                                                        struct timespec *tp,
                                                        dfsan_label clk_id_label,
@@ -611,7 +739,15 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id,
   return ret;
 }
 
-static void unpoison(const void *ptr, uptr size) {
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_clock_gettime(
+    clockid_t clk_id, struct timespec *tp, dfsan_label clk_id_label,
+    dfsan_label tp_label, dfsan_label *ret_label, dfsan_origin clk_id_origin,
+    dfsan_origin tp_origin, dfsan_origin *ret_origin) {
+  int ret = __dfsw_clock_gettime(clk_id, tp, clk_id_label, tp_label, ret_label);
+  return ret;
+}
+
+static void dfsan_set_zero_label(const void *ptr, uptr size) {
   dfsan_set_label(0, const_cast<void *>(ptr), size);
 }
 
@@ -624,11 +760,21 @@ __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label,
   void *handle = dlopen(filename, flag);
   link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle);
   if (map)
-    ForEachMappedRegion(map, unpoison);
+    ForEachMappedRegion(map, dfsan_set_zero_label);
   *ret_label = 0;
   return handle;
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_dlopen(
+    const char *filename, int flag, dfsan_label filename_label,
+    dfsan_label flag_label, dfsan_label *ret_label,
+    dfsan_origin filename_origin, dfsan_origin flag_origin,
+    dfsan_origin *ret_origin) {
+  void *handle =
+      __dfsw_dlopen(filename, flag, filename_label, flag_label, ret_label);
+  return handle;
+}
+
 static void *DFsanThreadStartFunc(void *arg) {
   DFsanThread *t = (DFsanThread *)arg;
   SetCurrentThread(t);
@@ -715,6 +861,17 @@ struct dl_iterate_phdr_info {
   void *data;
 };
 
+struct dl_iterate_phdr_origin_info {
+  int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
+                             size_t size, void *data, dfsan_label info_label,
+                             dfsan_label size_label, dfsan_label data_label,
+                             dfsan_label *ret_label, dfsan_origin info_origin,
+                             dfsan_origin size_origin, dfsan_origin data_origin,
+                             dfsan_origin *ret_origin);
+  void *callback;
+  void *data;
+};
+
 int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
   dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data;
   dfsan_set_label(0, *info);
@@ -728,6 +885,21 @@ int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) {
                                    0, &ret_label);
 }
 
+int dl_iterate_phdr_origin_cb(struct dl_phdr_info *info, size_t size,
+                              void *data) {
+  dl_iterate_phdr_origin_info *dipi = (dl_iterate_phdr_origin_info *)data;
+  dfsan_set_label(0, *info);
+  dfsan_set_label(0, const_cast<char *>(info->dlpi_name),
+                  strlen(info->dlpi_name) + 1);
+  dfsan_set_label(
+      0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)),
+      sizeof(*info->dlpi_phdr) * info->dlpi_phnum);
+  dfsan_label ret_label;
+  dfsan_origin ret_origin;
+  return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0,
+                                   0, &ret_label, 0, 0, 0, &ret_origin);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
     int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
                                size_t size, void *data, dfsan_label info_label,
@@ -740,6 +912,23 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr(
   return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi);
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_dl_iterate_phdr(
+    int (*callback_trampoline)(void *callback, struct dl_phdr_info *info,
+                               size_t size, void *data, dfsan_label info_label,
+                               dfsan_label size_label, dfsan_label data_label,
+                               dfsan_label *ret_label, dfsan_origin info_origin,
+                               dfsan_origin size_origin,
+                               dfsan_origin data_origin,
+                               dfsan_origin *ret_origin),
+    void *callback, void *data, dfsan_label callback_label,
+    dfsan_label data_label, dfsan_label *ret_label,
+    dfsan_origin callback_origin, dfsan_origin data_origin,
+    dfsan_origin *ret_origin) {
+  dl_iterate_phdr_origin_info dipi = {callback_trampoline, callback, data};
+  *ret_label = 0;
+  return dl_iterate_phdr(dl_iterate_phdr_origin_cb, &dipi);
+}
+
 // This function is only available for glibc 2.27 or newer.  Mark it weak so
 // linking succeeds with older glibcs.
 SANITIZER_WEAK_ATTRIBUTE void _dl_get_tls_static_info(size_t *sizep,
@@ -754,6 +943,13 @@ SANITIZER_INTERFACE_ATTRIBUTE void __dfsw__dl_get_tls_static_info(
   dfsan_set_label(0, alignp, sizeof(*alignp));
 }
 
+SANITIZER_INTERFACE_ATTRIBUTE void __dfso__dl_get_tls_static_info(
+    size_t *sizep, size_t *alignp, dfsan_label sizep_label,
+    dfsan_label alignp_label, dfsan_origin sizep_origin,
+    dfsan_origin alignp_origin) {
+  __dfsw__dl_get_tls_static_info(sizep, alignp, sizep_label, alignp_label);
+}
+
 SANITIZER_INTERFACE_ATTRIBUTE
 char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label,
                      dfsan_label buf_label, dfsan_label *ret_label) {

diff  --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp
index 7825f7aa8f32..1498c104160e 100644
--- a/compiler-rt/test/dfsan/custom.cpp
+++ b/compiler-rt/test/dfsan/custom.cpp
@@ -217,41 +217,68 @@ void test_bcmp() {
   ASSERT_ZERO_LABEL(rv);
 }
 
-#if !defined(ORIGIN_TRACKING)
 void test_memcpy() {
   char str1[] = "str1";
   char str2[sizeof(str1)];
   dfsan_set_label(i_label, &str1[3], 1);
 
-  ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1)));
+  DEFINE_AND_SAVE_ORIGINS(str1)
+
+  char *ptr2 = str2;
+  dfsan_set_label(j_label, &ptr2, sizeof(ptr2));
+
+  void *r = memcpy(ptr2, str1, sizeof(str1));
+  ASSERT_LABEL(r, j_label);
+  ASSERT_EQ_ORIGIN(r, ptr2);
   assert(0 == memcmp(str2, str1, sizeof(str1)));
   ASSERT_ZERO_LABEL(str2[0]);
   ASSERT_LABEL(str2[3], i_label);
+
+  for (int i = 0; i < sizeof(str2); ++i) {
+    if (!dfsan_get_label(str2[i]))
+      continue;
+    ASSERT_INIT_ORIGIN(&(str2[i]), str1_o[i]);
+  }
 }
 
 void test_memmove() {
   char str[] = "str1xx";
   dfsan_set_label(i_label, &str[3], 1);
 
-  ASSERT_ZERO_LABEL(memmove(str + 2, str, 4));
+  DEFINE_AND_SAVE_ORIGINS(str)
+
+  char *ptr = str + 2;
+  dfsan_set_label(j_label, &ptr, sizeof(ptr));
+
+  void *r = memmove(ptr, str, 4);
+  ASSERT_LABEL(r, j_label);
+  ASSERT_EQ_ORIGIN(r, ptr);
   assert(0 == memcmp(str + 2, "str1", 4));
-  for (int i = 0; i <= 4; ++i)
-    ASSERT_ZERO_LABEL(str[i]);
+  ASSERT_ZERO_LABEL(str[4]);
   ASSERT_LABEL(str[5], i_label);
+
+  for (int i = 0; i < 4; ++i) {
+    if (!dfsan_get_label(ptr[i]))
+      continue;
+    ASSERT_INIT_ORIGIN(&(ptr[i]), str_o[i]);
+  }
 }
 
 void test_memset() {
   char buf[8];
   int j = 'a';
+  char *ptr = buf;
   dfsan_set_label(j_label, &j, sizeof(j));
-
-  ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf)));
+  dfsan_set_label(k_label, &ptr, sizeof(ptr));
+  void *ret = memset(ptr, j, sizeof(buf));
+  ASSERT_LABEL(ret, k_label);
+  ASSERT_EQ_ORIGIN(ret, ptr);
   for (int i = 0; i < 8; ++i) {
     ASSERT_LABEL(buf[i], j_label);
+    ASSERT_EQ_ORIGIN(buf[i], j);
     assert(buf[i] == 'a');
   }
 }
-#endif // !defined(ORIGIN_TRACKING)
 
 void test_strcmp() {
   char str1[] = "str1", str2[] = "str2";
@@ -278,18 +305,34 @@ void test_strcmp() {
 #endif
 }
 
-#if !defined(ORIGIN_TRACKING)
 void test_strcat() {
   char src[] = "world";
+  int volatile x = 0; // buffer to ensure src and dst do not share origins
   char dst[] = "hello \0    ";
+  int volatile y = 0; // buffer to ensure dst and p do not share origins
   char *p = dst;
   dfsan_set_label(k_label, &p, sizeof(p));
   dfsan_set_label(i_label, src, sizeof(src));
   dfsan_set_label(j_label, dst, sizeof(dst));
+  dfsan_origin dst_o = dfsan_get_origin((long)dst[0]);
   char *ret = strcat(p, src);
   ASSERT_LABEL(ret, k_label);
+  ASSERT_EQ_ORIGIN(ret, p);
   assert(ret == dst);
   assert(strcmp(src, dst + 6) == 0);
+  // Origins are assigned for every 4 contiguous 4-aligned bytes. After
+  // appending src to dst, origins of src can overwrite origins of dst if their
+  // application adddresses are within [start_aligned_down, end_aligned_up).
+  // Other origins are not changed.
+  char *start_aligned_down = (char *)(((size_t)(dst + 6)) & ~3UL);
+  char *end_aligned_up = (char *)(((size_t)(dst + 11 + 4)) & ~3UL);
+  for (int i = 0; i < 12; ++i) {
+    if (dst + i < start_aligned_down || dst + i >= end_aligned_up) {
+      ASSERT_INIT_ORIGIN(&dst[i], dst_o);
+    } else {
+      ASSERT_INIT_ORIGIN_EQ_ORIGIN(&dst[i], src[0]);
+    }
+  }
   for (int i = 0; i < 6; ++i) {
     ASSERT_LABEL(dst[i], j_label);
   }
@@ -299,7 +342,6 @@ void test_strcat() {
   }
   ASSERT_LABEL(dst[11], j_label);
 }
-#endif // !defined(ORIGIN_TRACKING)
 
 void test_strlen() {
   char str1[] = "str1";
@@ -315,14 +357,22 @@ void test_strlen() {
 #endif
 }
 
-#if !defined(ORIGIN_TRACKING)
 void test_strdup() {
   char str1[] = "str1";
   dfsan_set_label(i_label, &str1[3], 1);
+  DEFINE_AND_SAVE_ORIGINS(str1)
 
   char *strd = strdup(str1);
+  ASSERT_ZERO_LABEL(strd);
   ASSERT_ZERO_LABEL(strd[0]);
   ASSERT_LABEL(strd[3], i_label);
+
+  for (int i = 0; i < strlen(strd); ++i) {
+    if (!dfsan_get_label(strd[i]))
+      continue;
+    ASSERT_INIT_ORIGIN(&(strd[i]), str1_o[i]);
+  }
+
   free(strd);
 }
 
@@ -339,16 +389,29 @@ void test_strncpy() {
   ASSERT_ZERO_LABEL(strd[1]);
   ASSERT_ZERO_LABEL(strd[2]);
   ASSERT_LABEL(strd[3], i_label);
+  ASSERT_INIT_ORIGIN_EQ_ORIGIN(&(strd[3]), str1[3]);
 
-  strd = strncpy(str2, str1, 3);
+  char *p2 = str2;
+  dfsan_set_label(j_label, &p2, sizeof(p2));
+  strd = strncpy(p2, str1, 3);
   assert(strd == str2);
   assert(strncmp(str1, str2, 3) == 0);
-  ASSERT_ZERO_LABEL(strd);
+  ASSERT_LABEL(strd, j_label);
+  ASSERT_EQ_ORIGIN(strd, p2);
+  // When -dfsan-combine-pointer-labels-on-load is on, strd's label propagates
+  // to strd[i]'s label. When ORIGIN_TRACKING is defined,
+  // -dfsan-combine-pointer-labels-on-load is always off, otherwise the flag
+  // is on by default.
+#if defined(ORIGIN_TRACKING)
   ASSERT_ZERO_LABEL(strd[0]);
   ASSERT_ZERO_LABEL(strd[1]);
   ASSERT_ZERO_LABEL(strd[2]);
+#else
+  ASSERT_LABEL(strd[0], j_label);
+  ASSERT_LABEL(strd[1], j_label);
+  ASSERT_LABEL(strd[2], j_label);
+#endif
 }
-#endif // !defined(ORIGIN_TRACKING)
 
 void test_strncmp() {
   char str1[] = "str1", str2[] = "str2";
@@ -523,7 +586,6 @@ void test_strchr() {
 #endif
 }
 
-#if !defined(ORIGIN_TRACKING)
 void test_calloc() {
   // With any luck this sequence of calls will cause calloc to return the same
   // pointer both times.  This is probably the best we can do to test this
@@ -538,6 +600,7 @@ void test_calloc() {
   free(crv);
 }
 
+#if !defined(ORIGIN_TRACKING)
 void test_recvmmsg() {
   int sockfds[2];
   int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
@@ -630,12 +693,14 @@ void test_recvmsg() {
   close(sockfds[0]);
   close(sockfds[1]);
 }
+#endif // !defined(ORIGIN_TRACKING)
 
 void test_read() {
   char buf[16];
   dfsan_set_label(i_label, buf, 1);
   dfsan_set_label(j_label, buf + 15, 1);
 
+  DEFINE_AND_SAVE_ORIGINS(buf)
   ASSERT_LABEL(buf[0], i_label);
   ASSERT_LABEL(buf[15], j_label);
 
@@ -645,6 +710,7 @@ void test_read() {
   ASSERT_ZERO_LABEL(rv);
   ASSERT_ZERO_LABEL(buf[0]);
   ASSERT_ZERO_LABEL(buf[15]);
+  ASSERT_SAVED_ORIGINS(buf)
   close(fd);
 }
 
@@ -653,6 +719,7 @@ void test_pread() {
   dfsan_set_label(i_label, buf, 1);
   dfsan_set_label(j_label, buf + 15, 1);
 
+  DEFINE_AND_SAVE_ORIGINS(buf)
   ASSERT_LABEL(buf[0], i_label);
   ASSERT_LABEL(buf[15], j_label);
 
@@ -662,6 +729,7 @@ void test_pread() {
   ASSERT_ZERO_LABEL(rv);
   ASSERT_ZERO_LABEL(buf[0]);
   ASSERT_ZERO_LABEL(buf[15]);
+  ASSERT_SAVED_ORIGINS(buf)
   close(fd);
 }
 
@@ -678,12 +746,15 @@ void test_dlopen() {
 void test_clock_gettime() {
   struct timespec tp;
   dfsan_set_label(j_label, ((char *)&tp) + 3, 1);
+  dfsan_origin origin = dfsan_get_origin((long)(((char *)&tp)[3]));
   int t = clock_gettime(CLOCK_REALTIME, &tp);
   assert(t == 0);
   ASSERT_ZERO_LABEL(t);
   ASSERT_ZERO_LABEL(((char *)&tp)[3]);
+  ASSERT_ORIGIN(((char *)&tp)[3], origin);
 }
 
+#if !defined(ORIGIN_TRACKING)
 void test_ctime_r() {
   char *buf = (char*) malloc(64);
   time_t t = 0;
@@ -704,6 +775,7 @@ void test_ctime_r() {
   ASSERT_LABEL(ret, j_label);
   ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
 }
+#endif // !defined(ORIGIN_TRACKING)
 
 static int write_callback_count = 0;
 static int last_fd;
@@ -728,6 +800,8 @@ void test_dfsan_set_write_callback() {
 
   write_callback_count = 0;
 
+  DEFINE_AND_SAVE_ORIGINS(buf)
+
   // Callback should be invoked on every call to write().
   int res = write(fd, buf, buf_len);
   assert(write_callback_count == 1);
@@ -736,12 +810,21 @@ void test_dfsan_set_write_callback() {
   ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf));
   ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count));
 
+  for (int i = 0; i < buf_len; ++i)
+    ASSERT_ORIGIN(last_buf[i], buf_o[i]);
+
+  ASSERT_ZERO_ORIGINS(&last_count, sizeof(last_count));
+
   // Add a label to write() arguments.  Check that the labels are readable from
   // the values passed to the callback.
   dfsan_set_label(i_label, &fd, sizeof(fd));
   dfsan_set_label(j_label, &(buf[3]), 1);
   dfsan_set_label(k_label, &buf_len, sizeof(buf_len));
 
+  dfsan_origin fd_o = dfsan_get_origin((long)fd);
+  dfsan_origin buf3_o = dfsan_get_origin((long)(buf[3]));
+  dfsan_origin buf_len_o = dfsan_get_origin((long)buf_len);
+
   res = write(fd, buf, buf_len);
   assert(write_callback_count == 2);
   ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
@@ -749,10 +832,27 @@ void test_dfsan_set_write_callback() {
   ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label);
   ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label);
   ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label);
+  ASSERT_ZERO_ORIGINS(&res, sizeof(res));
+  ASSERT_INIT_ORIGINS(&last_fd, sizeof(last_fd), fd_o);
+  ASSERT_INIT_ORIGINS(&last_buf[3], sizeof(last_buf[3]), buf3_o);
+
+  // Origins are assigned for every 4 contiguous 4-aligned bytes. After
+  // appending src to dst, origins of src can overwrite origins of dst if their
+  // application adddresses are within an aligned range. Other origins are not
+  // changed.
+  for (int i = 0; i < buf_len; ++i) {
+    size_t i_addr = size_t(&last_buf[i]);
+    if (((size_t(&last_buf[3]) & ~3UL) > i_addr) ||
+        (((size_t(&last_buf[3]) + 4) & ~3UL) <= i_addr))
+      ASSERT_ORIGIN(last_buf[i], buf_o[i]);
+  }
+
+  ASSERT_INIT_ORIGINS(&last_count, sizeof(last_count), buf_len_o);
 
   dfsan_set_write_callback(NULL);
 }
 
+#if !defined(ORIGIN_TRACKING)
 void test_fgets() {
   char *buf = (char*) malloc(128);
   FILE *f = fopen("/etc/passwd", "r");
@@ -1126,7 +1226,6 @@ void test_pthread_create() {
 // check-wrappers script.
 void test_pthread_join() {}
 
-#if !defined(ORIGIN_TRACKING)
 int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
                             void *data) {
   assert(data == (void *)3);
@@ -1151,11 +1250,16 @@ void test__dl_get_tls_static_info() {
   size_t sizep = 0, alignp = 0;
   dfsan_set_label(i_label, &sizep, sizeof(sizep));
   dfsan_set_label(i_label, &alignp, sizeof(alignp));
+  dfsan_origin sizep_o = dfsan_get_origin(sizep);
+  dfsan_origin alignp_o = dfsan_get_origin(alignp);
   _dl_get_tls_static_info(&sizep, &alignp);
   ASSERT_ZERO_LABEL(sizep);
   ASSERT_ZERO_LABEL(alignp);
+  ASSERT_ORIGIN(sizep, sizep_o);
+  ASSERT_ORIGIN(alignp, alignp_o);
 }
 
+#if !defined(ORIGIN_TRACKING)
 void test_strrchr() {
   char str1[] = "str1str1";
   dfsan_set_label(i_label, &str1[7], 1);
@@ -1559,17 +1663,17 @@ int main(void) {
   assert(i_j_label != j_label);
   assert(i_j_label != k_label);
 
-#if !defined(ORIGIN_TRACKING)
   test__dl_get_tls_static_info();
-#endif // !defined(ORIGIN_TRACKING)
   test_bcmp();
-#if !defined(ORIGIN_TRACKING)
   test_calloc();
   test_clock_gettime();
+#if !defined(ORIGIN_TRACKING)
   test_ctime_r();
+#endif // !defined(ORIGIN_TRACKING)
   test_dfsan_set_write_callback();
   test_dl_iterate_phdr();
   test_dlopen();
+#if !defined(ORIGIN_TRACKING)
   test_epoll_wait();
   test_fgets();
 #endif // !defined(ORIGIN_TRACKING)
@@ -1591,18 +1695,18 @@ int main(void) {
   test_memchr();
 #endif // !defined(ORIGIN_TRACKING)
   test_memcmp();
-#if !defined(ORIGIN_TRACKING)
   test_memcpy();
   test_memmove();
   test_memset();
+#if !defined(ORIGIN_TRACKING)
   test_nanosleep();
   test_poll();
-  test_pread();
 #endif // !defined(ORIGIN_TRACKING)
+  test_pread();
   test_pthread_create();
   test_pthread_join();
-#if !defined(ORIGIN_TRACKING)
   test_read();
+#if !defined(ORIGIN_TRACKING)
   test_recvmmsg();
   test_recvmsg();
   test_sched_getaffinity();
@@ -1621,17 +1725,15 @@ int main(void) {
   test_strcasecmp();
   test_strchr();
   test_strcmp();
-#if !defined(ORIGIN_TRACKING)
   test_strcat();
+#if !defined(ORIGIN_TRACKING)
   test_strcpy();
-  test_strdup();
 #endif // !defined(ORIGIN_TRACKING)
+  test_strdup();
   test_strlen();
   test_strncasecmp();
   test_strncmp();
-#if !defined(ORIGIN_TRACKING)
   test_strncpy();
-#endif // !defined(ORIGIN_TRACKING)
   test_strpbrk();
 #if !defined(ORIGIN_TRACKING)
   test_strrchr();


        


More information about the llvm-commits mailing list