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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits