[llvm-branch-commits] [sanitizer] Add TryMemCpy (PR #112668)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Oct 16 23:44:27 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Vitaly Buka (vitalybuka)
<details>
<summary>Changes</summary>
For posix implementation is similar to
`IsAccessibleMemoryRange`, using `pipe`.
We need this because we can't rely on non-atomic
`IsAccessibleMemoryRange` + `memcpy`, as the
protection or mapping may change and we may
crash.
---
Full diff: https://github.com/llvm/llvm-project/pull/112668.diff
5 Files Affected:
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_common.h (+4)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp (+5)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp (+38)
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_win.cpp (+5)
- (modified) compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp (+41-4)
``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 082d2158e579bd..9b1e58f5e7a61d 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -268,7 +268,11 @@ class ScopedErrorReportLock {
extern uptr stoptheworld_tracer_pid;
extern uptr stoptheworld_tracer_ppid;
+// Returns true if we can read a memory range.
bool IsAccessibleMemoryRange(uptr beg, uptr size);
+// Returns true if we can read a memory range starting at `src`, and copies
+// content into `dest`.
+bool TryMemCpy(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_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
index 75dcf546729f6e..c2ace46c946587 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -444,6 +444,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
return status == ZX_OK;
}
+bool TryMemCpy(void *dest, const void *src, uptr n) {
+ // TODO: implement.
+ return false;
+}
+
// FIXME implement on this platform.
void GetMemoryProfile(fill_profile_f cb, uptr *stats) {}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index f87af4bb3a5a6a..80b36efc3ef627 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -325,6 +325,44 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
return true;
}
+bool TryMemCpy(void *dest, const void *src, uptr n) {
+ int sock_pair[2];
+ if (pipe(sock_pair))
+ return false;
+
+ auto cleanup = at_scope_exit([&]() {
+ internal_close(sock_pair[0]);
+ internal_close(sock_pair[1]);
+ });
+
+ SetNonBlock(sock_pair[0]);
+ SetNonBlock(sock_pair[1]);
+
+ char *d = static_cast<char *>(dest);
+ const char *s = static_cast<const char *>(src);
+
+ while (n) {
+ int e;
+ uptr w = internal_write(sock_pair[1], s, n);
+ if (internal_iserror(w, &e)) {
+ CHECK_EQ(EFAULT, e);
+ return false;
+ }
+ s += w;
+ n -= w;
+
+ while (w) {
+ uptr r = internal_read(sock_pair[0], d, w);
+ CHECK(!internal_iserror(r, &e));
+
+ d += r;
+ w -= r;
+ }
+ }
+
+ return true;
+}
+
void PlatformPrepareForSandboxing(void *args) {
// Some kinds of sandboxes may forbid filesystem access, so we won't be able
// to read the file mappings from /proc/self/maps. Luckily, neither the
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index 6fb947aa6d6c26..ea513d5f263fe2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -968,6 +968,11 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
return true;
}
+bool TryMemCpy(void *dest, const void *src, uptr n) {
+ // TODO: implement.
+ return false;
+}
+
bool SignalContext::IsStackOverflow() const {
return (DWORD)GetType() == EXCEPTION_STACK_OVERFLOW;
}
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 9feb22221f005e..d641567d2b5964 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
@@ -13,11 +13,14 @@
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_POSIX
-#include "sanitizer_common/sanitizer_common.h"
-#include "gtest/gtest.h"
+# include <pthread.h>
+# include <sys/mman.h>
-#include <pthread.h>
-#include <sys/mman.h>
+# include <numeric>
+
+# include "gmock/gmock.h"
+# include "gtest/gtest.h"
+# include "sanitizer_common/sanitizer_common.h"
namespace __sanitizer {
@@ -93,6 +96,40 @@ TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {
munmap((void *)mem, size);
}
+TEST(SanitizerCommon, TryMemCpy) {
+ std::vector<char> src(10000000);
+ std::iota(src.begin(), src.end(), 123);
+ std::vector<char> dst;
+
+ using ::testing::ElementsAreArray;
+
+ dst.assign(1, 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ dst.assign(100, 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ dst.assign(534, 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ dst.assign(GetPageSize(), 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ dst.assign(src.size(), 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ dst.assign(src.size() - 1, 0);
+ ASSERT_TRUE(TryMemCpy(dst.data(), src.data(), dst.size()));
+ EXPECT_THAT(dst, ElementsAreArray(src.data(), dst.size()));
+
+ EXPECT_FALSE(TryMemCpy(dst.data(), nullptr, dst.size()));
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
``````````
</details>
https://github.com/llvm/llvm-project/pull/112668
More information about the llvm-branch-commits
mailing list