[compiler-rt] r193338 - [msan] Fix invalid origin copying.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Thu Oct 24 04:56:03 PDT 2013


Author: eugenis
Date: Thu Oct 24 06:56:03 2013
New Revision: 193338

URL: http://llvm.org/viewvc/llvm-project?rev=193338&view=rev
Log:
[msan] Fix invalid origin copying.

Origin copying may destroy valid origin info. This is caused by
__msan_copy_origin widening the address range to the nearest 4-byte aligned
addresses both on the left and on the right. If the target buffer is
uninitialized and the source is fully initialized, this will result in
overriding valid origin of target buffer with stale (possibly 0) origin of the
source buffer.

With this change the widened origin is copied only if corresponding shadow
values are non zero.

Modified:
    compiler-rt/trunk/lib/msan/msan.h
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/msan/tests/msan_test.cc

Modified: compiler-rt/trunk/lib/msan/msan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=193338&r1=193337&r2=193338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.h (original)
+++ compiler-rt/trunk/lib/msan/msan.h Thu Oct 24 06:56:03 2013
@@ -25,11 +25,12 @@
 # define MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 1
 #endif
 
-#define MEM_TO_SHADOW(mem) (((uptr)mem)       & ~0x400000000000ULL)
-#define MEM_TO_ORIGIN(mem) (MEM_TO_SHADOW(mem) + 0x200000000000ULL)
-#define MEM_IS_APP(mem)    ((uptr)mem >=         0x600000000000ULL)
-#define MEM_IS_SHADOW(mem) ((uptr)mem >=         0x200000000000ULL && \
-                            (uptr)mem <=         0x400000000000ULL)
+#define MEM_TO_SHADOW(mem)       (((uptr)mem) & ~0x400000000000ULL)
+#define SHADOW_TO_ORIGIN(shadow) (((uptr)shadow) + 0x200000000000ULL)
+#define MEM_TO_ORIGIN(mem)       (SHADOW_TO_ORIGIN(MEM_TO_SHADOW(mem)))
+#define MEM_IS_APP(mem)          ((uptr)mem >= 0x600000000000ULL)
+#define MEM_IS_SHADOW(mem) \
+  ((uptr)mem >= 0x200000000000ULL && (uptr)mem <= 0x400000000000ULL)
 
 const int kMsanParamTlsSizeInWords = 100;
 const int kMsanRetvalTlsSizeInWords = 100;

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=193338&r1=193337&r2=193338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Thu Oct 24 06:56:03 2013
@@ -1278,15 +1278,41 @@ void __msan_clear_and_unpoison(void *a,
   fast_memset((void*)MEM_TO_SHADOW((uptr)a), 0, size);
 }
 
+u32 get_origin_if_poisoned(uptr a, uptr size) {
+  unsigned char *s = (unsigned char *)MEM_TO_SHADOW(a);
+  for (uptr i = 0; i < size; ++i)
+    if (s[i])
+      return *(uptr *)SHADOW_TO_ORIGIN((s + i) & ~3UL);
+  return 0;
+}
+
 void __msan_copy_origin(void *dst, const void *src, uptr size) {
   if (!__msan_get_track_origins()) return;
   if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
-  uptr d = MEM_TO_ORIGIN(dst);
-  uptr s = MEM_TO_ORIGIN(src);
-  uptr beg = d & ~3UL;  // align down.
-  uptr end = (d + size + 3) & ~3UL;  // align up.
-  s = s & ~3UL;  // align down.
-  fast_memcpy((void*)beg, (void*)s, end - beg);
+  uptr d = (uptr)dst;
+  uptr beg = d & ~3UL;
+  // Copy left unaligned origin if that memory is poisoned.
+  if (beg < d) {
+    u32 o = get_origin_if_poisoned(beg, d - beg);
+    if (o)
+      *(uptr *)MEM_TO_ORIGIN(beg) = o;
+    beg += 4;
+  }
+
+  uptr end = (d + size + 3) & ~3UL;
+  // Copy right unaligned origin if that memory is poisoned.
+  if (end > d + size) {
+    u32 o = get_origin_if_poisoned(d + size, end - d - size);
+    if (o)
+      *(uptr *)MEM_TO_ORIGIN(end - 4) = o;
+    end -= 4;
+  }
+
+  if (beg < end) {
+    // Align src up.
+    uptr s = ((uptr)src + 3) & ~3UL;
+    fast_memcpy((void*)MEM_TO_ORIGIN(beg), (void*)MEM_TO_ORIGIN(s), end - beg);
+  }
 }
 
 void __msan_copy_poison(void *dst, const void *src, uptr size) {

Modified: compiler-rt/trunk/lib/msan/tests/msan_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/tests/msan_test.cc?rev=193338&r1=193337&r2=193338&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/tests/msan_test.cc (original)
+++ compiler-rt/trunk/lib/msan/tests/msan_test.cc Thu Oct 24 06:56:03 2013
@@ -1210,6 +1210,35 @@ TEST(MemorySanitizer, memcpy) {
   EXPECT_POISONED(y[1]);
 }
 
+void TestUnalignedMemcpy(int left, int right, bool src_is_aligned) {
+  const int sz = 20;
+  char *dst = (char *)malloc(sz);
+  U4 origin = __msan_get_origin(dst);
+
+  char *src = (char *)malloc(sz);
+  memset(src, 0, sz);
+
+  memcpy(dst + left, src_is_aligned ? src + left : src, sz - left - right);
+  for (int i = 0; i < left; ++i)
+    EXPECT_POISONED_O(dst[i], origin);
+  for (int i = 0; i < right; ++i)
+    EXPECT_POISONED_O(dst[sz - i - 1], origin);
+  EXPECT_NOT_POISONED(dst[left]);
+  EXPECT_NOT_POISONED(dst[sz - right - 1]);
+
+  free(dst);
+  free(src);
+}
+
+TEST(MemorySanitizer, memcpy_unaligned) {
+  for (int i = 0; i < 4; ++i) {
+    for (int j = 0; j < 4; ++j) {
+      TestUnalignedMemcpy(i, j, true);
+      TestUnalignedMemcpy(i, j, false);
+    }
+  }
+}
+
 TEST(MemorySanitizer, memmove) {
   char* x = new char[2];
   char* y = new char[2];





More information about the llvm-commits mailing list