[compiler-rt] 7106de9 - [sanitizer] Add MemCpyAccessible (#112794)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 17 17:28:01 PDT 2024
Author: Vitaly Buka
Date: 2024-10-17T17:27:57-07:00
New Revision: 7106de9573c29db5d107a2f4ab02d8621eea2510
URL: https://github.com/llvm/llvm-project/commit/7106de9573c29db5d107a2f4ab02d8621eea2510
DIFF: https://github.com/llvm/llvm-project/commit/7106de9573c29db5d107a2f4ab02d8621eea2510.diff
LOG: [sanitizer] Add MemCpyAccessible (#112794)
A layer over `TryMemCpy` to copy only available pages.
Added:
Modified:
compiler-rt/lib/sanitizer_common/sanitizer_common.h
compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 3a28420ed02d78..0b5e68c5fd7978 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -275,6 +275,8 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size);
// the source range cannot be read, in which case the contents of `dest` are
// undefined.
bool TryMemCpy(void *dest, const void *src, uptr n);
+// Copies accessible memory, and zero fill inaccessible.
+void MemCpyAccessible(void *dest, const void *src, uptr n);
// Error report formatting.
const char *StripPathPrefix(const char *filepath,
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
index 684720963a8dcb..f275e81ff04169 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
@@ -219,6 +219,32 @@ static void StopStackDepotBackgroundThread() {
static void StopStackDepotBackgroundThread() {}
#endif
+void MemCpyAccessible(void *dest, const void *src, uptr n) {
+ if (TryMemCpy(dest, src, n))
+ return;
+
+ const uptr page_size = GetPageSize();
+ uptr b = reinterpret_cast<uptr>(src);
+ uptr b_up = RoundUpTo(b, page_size);
+
+ uptr e = reinterpret_cast<uptr>(src) + n;
+ uptr e_down = RoundDownTo(e, page_size);
+
+ auto copy_or_zero = [dest, src](uptr beg, uptr end) {
+ const uptr udest = reinterpret_cast<uptr>(dest);
+ const uptr usrc = reinterpret_cast<uptr>(src);
+ void *d = reinterpret_cast<void *>(udest + (beg - usrc));
+ const uptr size = end - beg;
+ if (!TryMemCpy(d, reinterpret_cast<void *>(beg), size))
+ internal_memset(d, 0, size);
+ };
+
+ copy_or_zero(b, b_up);
+ for (uptr p = b_up; p < e_down; p += page_size)
+ copy_or_zero(p, p + page_size);
+ copy_or_zero(e_down, e);
+}
+
} // namespace __sanitizer
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
index 658ca60175b3bd..5016b09c15307f 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
@@ -127,6 +127,43 @@ TEST(SanitizerCommon, TryMemCpyNull) {
EXPECT_FALSE(TryMemCpy(dst.data(), nullptr, dst.size()));
}
+TEST(SanitizerCommon, MemCpyAccessible) {
+ const int page_num = 1000;
+ const int page_size = GetPageSize();
+ InternalMmapVector<char> src(page_num * page_size);
+ std::iota(src.begin(), src.end(), 123);
+ std::vector<char> dst;
+ std::vector<char> exp = {src.begin(), src.end()};
+
+ // Protect some pages.
+ for (int i = 7; i < page_num; i *= 2) {
+ mprotect(src.data() + i * page_size, page_size, PROT_NONE);
+ std::fill(exp.data() + i * page_size, exp.data() + (i + 1) * page_size, 0);
+ }
+
+ dst.assign(src.size(), 0);
+ EXPECT_FALSE(TryMemCpy(dst.data(), src.data(), dst.size()));
+
+ // Full page aligned range with mprotect pages.
+ dst.assign(src.size(), 0);
+ MemCpyAccessible(dst.data(), src.data(), dst.size());
+ EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin()));
+
+ // Misaligned range with mprotect pages.
+ size_t offb = 3;
+ size_t offe = 7;
+ dst.assign(src.size() - offb - offe, 0);
+ MemCpyAccessible(dst.data(), src.data() + offb, dst.size());
+ EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin() + offb));
+
+ // Misaligned range with ends in mprotect pages.
+ offb = 3 + 7 * page_size;
+ offe = 7 + 14 * page_size;
+ dst.assign(src.size() - offb - offe, 0);
+ MemCpyAccessible(dst.data(), src.data() + offb, dst.size());
+ EXPECT_TRUE(std::equal(dst.begin(), dst.end(), exp.begin() + offb));
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
More information about the llvm-commits
mailing list