[compiler-rt] [sanitizer] Large range support in IsAccessibleMemoryRange (PR #112665)

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 17 11:17:27 PDT 2024


https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/112665

>From 15f54502722a07b4c69ad079934a179d71b840ac Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Wed, 16 Oct 2024 23:06:02 -0700
Subject: [PATCH 1/4] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 .../sanitizer_posix_libcdep.cpp               | 52 ++++++++++++-------
 .../tests/sanitizer_posix_test.cpp            | 11 ++++
 2 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 9ffb36f812c45d..0f8fdd4487efb6 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -288,26 +288,42 @@ bool SignalContext::IsStackOverflow() const {
 
 #endif  // SANITIZER_GO
 
+static void SetNonBlock(int fd) {
+  int res = fcntl(fd, F_GETFL, 0);
+  CHECK(!internal_iserror(res, nullptr));
+
+  res |= O_NONBLOCK;
+  res = fcntl(fd, F_SETFL, res);
+  CHECK(!internal_iserror(res, nullptr));
+}
+
 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
-  uptr page_size = GetPageSizeCached();
-  // Checking too large memory ranges is slow.
-  CHECK_LT(size, page_size * 10);
-  int sock_pair[2];
-  if (pipe(sock_pair))
-    return false;
-  uptr bytes_written =
-      internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
-  int write_errno;
-  bool result;
-  if (internal_iserror(bytes_written, &write_errno)) {
-    CHECK_EQ(EFAULT, write_errno);
-    result = false;
-  } else {
-    result = (bytes_written == size);
+  for (uptr to_write = size; to_write;) {
+    // `read` from `sock_pair[0]` into a dummy buffer to free up the pipe buffer
+    // for more `write` is slower than just recreating a pipe.
+    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[1]);
+
+    int write_errno;
+    uptr bytes_written =
+        internal_write(sock_pair[1], reinterpret_cast<char *>(beg), to_write);
+    if (internal_iserror(bytes_written, &write_errno)) {
+      CHECK_EQ(EFAULT, write_errno);
+      return false;
+    }
+    beg += bytes_written;
+    to_write -= bytes_written;
   }
-  internal_close(sock_pair[0]);
-  internal_close(sock_pair[1]);
-  return result;
+
+  return true;
 }
 
 void PlatformPrepareForSandboxing(void *args) {
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 bed19d15a8ec77..9feb22221f005e 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_posix_test.cpp
@@ -82,6 +82,17 @@ TEST(SanitizerCommon, IsAccessibleMemoryRange) {
   munmap((void *)mem, 3 * page_size);
 }
 
+TEST(SanitizerCommon, IsAccessibleMemoryRangeLarge) {
+  const int size = GetPageSize() * 10000;
+
+  uptr mem = (uptr)mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
+                        -1, 0);
+
+  EXPECT_TRUE(IsAccessibleMemoryRange(mem, size));
+
+  munmap((void *)mem, size);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_POSIX

>From 8652b674755dca83a6f8b1a97f7b4417b6ce936a Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Wed, 16 Oct 2024 23:15:55 -0700
Subject: [PATCH 2/4] simplify

Created using spr 1.3.4
---
 .../lib/sanitizer_common/sanitizer_posix_libcdep.cpp  | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 0f8fdd4487efb6..f87af4bb3a5a6a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -298,7 +298,7 @@ static void SetNonBlock(int fd) {
 }
 
 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
-  for (uptr to_write = size; to_write;) {
+  while (size) {
     // `read` from `sock_pair[0]` into a dummy buffer to free up the pipe buffer
     // for more `write` is slower than just recreating a pipe.
     int sock_pair[2];
@@ -313,14 +313,13 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
     SetNonBlock(sock_pair[1]);
 
     int write_errno;
-    uptr bytes_written =
-        internal_write(sock_pair[1], reinterpret_cast<char *>(beg), to_write);
-    if (internal_iserror(bytes_written, &write_errno)) {
+    uptr w = internal_write(sock_pair[1], reinterpret_cast<char *>(beg), size);
+    if (internal_iserror(w, &write_errno)) {
       CHECK_EQ(EFAULT, write_errno);
       return false;
     }
-    beg += bytes_written;
-    to_write -= bytes_written;
+    size -= w;
+    beg += w;
   }
 
   return true;

>From 53748bc55c0d07f6643b3416035cc58e4da6a11c Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 17 Oct 2024 10:45:16 -0700
Subject: [PATCH 3/4] format

Created using spr 1.3.4
---
 compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 9b8f63bea586a3..ef4c4cac0e5138 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -299,8 +299,8 @@ static void SetNonBlock(int fd) {
 
 bool IsAccessibleMemoryRange(uptr beg, uptr size) {
   while (size) {
-    // `read` from `fds[0]` into a dummy buffer to free up the pipe buffer
-    // for more `write` is slower than just recreating a pipe.
+    // `read` from `fds[0]` into a dummy buffer to free up the pipe buffer for
+    // more `write` is slower than just recreating a pipe.
     int fds[2];
     if (pipe(fds))
       return false;

>From 5ec3379686c90ccc1ce3cebb9729c8af021f31b1 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 17 Oct 2024 10:52:12 -0700
Subject: [PATCH 4/4] no AGAIN

Created using spr 1.3.4
---
 .../lib/sanitizer_common/sanitizer_posix_libcdep.cpp | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index ef4c4cac0e5138..7e00a2a0f0c082 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -315,14 +315,10 @@ bool IsAccessibleMemoryRange(uptr beg, uptr size) {
     int write_errno;
     uptr w = internal_write(fds[1], reinterpret_cast<char *>(beg), size);
     if (internal_iserror(w, &write_errno)) {
-      switch (write_errno) {
-        case EINTR:
-        case EAGAIN:
-          continue;
-        default:
-          CHECK_EQ(EFAULT, write_errno);
-          return false;
-      }
+      if (write_errno == EINTR)
+        continue;
+      CHECK_EQ(EFAULT, write_errno);
+      return false;
     }
     size -= w;
     beg += w;



More information about the llvm-commits mailing list