[compiler-rt] Reapply "[sanitizer] intercept getservent_r, getservbyname_r, getservbyport_r" (#133358) (PR #133528)
Florian Mayer via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 31 10:51:49 PDT 2025
https://github.com/fmayer updated https://github.com/llvm/llvm-project/pull/133528
>From 2aafa62ee8e269a396ba36b006ae835013f55496 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 28 Mar 2025 15:25:55 -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
---
compiler-rt/lib/msan/tests/msan_test.cpp | 69 +++++++++++++++++++
.../sanitizer_common_interceptors.inc | 68 ++++++++++++++++++
.../sanitizer_platform_interceptors.h | 4 ++
.../sanitizer_platform_limits_posix.h | 9 +++
4 files changed, 150 insertions(+)
diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp
index a126dd4fdd55e..8b7df85e0ff04 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cpp
+++ b/compiler-rt/lib/msan/tests/msan_test.cpp
@@ -4908,5 +4908,74 @@ TEST(MemorySanitizer, timer_create) {
EXPECT_POISONED(timer2);
timer_delete(timer);
}
+
+TEST(MemorySanitizer, getservent_r) {
+ struct servent result_buf;
+ struct servent *result;
+ char buf[1024];
+ EXPECT_POISONED(result_buf);
+ EXPECT_POISONED(result);
+ EXPECT_POISONED(buf);
+ ASSERT_EQ(getservent_r(&result_buf, buf, sizeof(buf), &result), 0);
+ EXPECT_NOT_POISONED(result);
+ ASSERT_NE(result, nullptr);
+ EXPECT_NOT_POISONED(result_buf);
+ EXPECT_NOT_POISONED(buf);
+}
+
+TEST(MemorySanitizer, getservbyname_r) {
+ struct servent result_buf;
+ struct servent *result;
+ char buf[1024];
+ EXPECT_POISONED(result_buf);
+ EXPECT_POISONED(result);
+ EXPECT_POISONED(buf);
+ ASSERT_EQ(
+ getservbyname_r("ssh", nullptr, &result_buf, buf, sizeof(buf), &result),
+ 0);
+ EXPECT_NOT_POISONED(result);
+ // If this fails, check /etc/services if "ssh" exists. I picked this because
+ // it should exist everywhere, if it doesn't, I am sorry. Disable the test
+ // then please.
+ ASSERT_NE(result, nullptr);
+ EXPECT_NOT_POISONED(result_buf);
+ EXPECT_NOT_POISONED(buf);
+}
+
+TEST(MemorySanitizer, getservbyname_r_unknown) {
+ struct servent result_buf;
+ struct servent *result;
+ char buf[1024];
+ EXPECT_POISONED(result_buf);
+ EXPECT_POISONED(result);
+ EXPECT_POISONED(buf);
+ ASSERT_EQ(getservbyname_r("invalidhadfuiasdhi", nullptr, &result_buf, buf,
+ sizeof(buf), &result),
+ 0);
+ EXPECT_NOT_POISONED(result);
+ ASSERT_EQ(result, nullptr);
+ EXPECT_POISONED(result_buf);
+ EXPECT_POISONED(buf);
+}
+
+TEST(MemorySanitizer, getservbyport_r) {
+ struct servent result_buf;
+ struct servent *result;
+ char buf[1024];
+ EXPECT_POISONED(result_buf);
+ EXPECT_POISONED(result);
+ EXPECT_POISONED(buf);
+ ASSERT_EQ(getservbyport_r(htons(22), nullptr, &result_buf, buf, sizeof(buf),
+ &result),
+ 0);
+ EXPECT_NOT_POISONED(result);
+ // If this fails, check /etc/services if "ssh" exists. I picked this because
+ // it should exist everywhere, if it doesn't, I am sorry. Disable the test
+ // then please.
+ ASSERT_NE(result, nullptr);
+ EXPECT_NOT_POISONED(result_buf);
+ EXPECT_NOT_POISONED(buf);
+}
+
#endif
} // namespace
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 761dbd3f5a679..29b977c050579 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -10279,6 +10279,71 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
# define INIT_FREADLINK
#endif
+#if SANITIZER_INTERCEPT_GETSERVENT_R || SANITIZER_INTERCEPT_GETSERVBYNAME_R || \
+ SANITIZER_INTERCEPT_GETSERVBYPORT_R
+
+UNUSED static void HandleGetServentReentrantResult(
+ void *ctx, int res, struct __sanitizer_servent *result_buf, char *buf,
+ SIZE_T buflen, struct __sanitizer_servent **result) {
+ if (res)
+ return;
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)result, sizeof(void *));
+ if (*result) {
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (char *)*result,
+ sizeof(__sanitizer_servent));
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
+ }
+}
+
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVENT_R
+INTERCEPTOR(int, getservent_r, struct __sanitizer_servent *result_buf,
+ char *buf, SIZE_T buflen, struct __sanitizer_servent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getservent_r, result_buf, buf, buflen, result);
+ int res = REAL(getservent_r)(result_buf, buf, buflen, result);
+ HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+ return res;
+}
+# define INIT_GETSERVENT_R COMMON_INTERCEPT_FUNCTION(getservent_r)
+#else
+# define INIT_GETSERVENT_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVBYNAME_R
+INTERCEPTOR(int, getservbyname_r, const char *name, const char *proto,
+ struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
+ struct __sanitizer_servent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getservbyname_r, name, proto, result_buf, buf,
+ buflen, result);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, name, internal_strlen(name));
+ int res = REAL(getservbyname_r)(name, proto, result_buf, buf, buflen, result);
+ HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+ return res;
+}
+# define INIT_GETSERVBYNAME_R COMMON_INTERCEPT_FUNCTION(getservbyname_r)
+#else
+# define INIT_GETSERVBYNAME_R
+#endif
+
+#if SANITIZER_INTERCEPT_GETSERVBYPORT_R
+INTERCEPTOR(int, getservbyport_r, int port, const char *proto,
+ struct __sanitizer_servent *result_buf, char *buf, SIZE_T buflen,
+ struct __sanitizer_servent **result) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, getservbyport_r, port, proto, result_buf, buf,
+ buflen, result);
+ int res = REAL(getservbyport_r)(port, proto, result_buf, buf, buflen, result);
+ HandleGetServentReentrantResult(ctx, res, result_buf, buf, buflen, result);
+ return res;
+}
+# define INIT_GETSERVBYPORT_R COMMON_INTERCEPT_FUNCTION(getservbyport_r)
+#else
+# define INIT_GETSERVBYPORT_R
+#endif
+
#include "sanitizer_common_interceptors_netbsd_compat.inc"
namespace __sanitizer {
@@ -10604,4 +10669,7 @@ static void InitializeCommonInterceptors() {
INIT_FREADLINK;
INIT___PRINTF_CHK;
+ INIT_GETSERVENT_R;
+ INIT_GETSERVBYNAME_R;
+ INIT_GETSERVBYPORT_R;
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 468b5494d0092..b8f2f738e7478 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -645,6 +645,10 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
# define SI_MAC_OS_DEPLOYMENT_MIN_13_00 0
#endif
#define SANITIZER_INTERCEPT_FREADLINK (SI_MAC && SI_MAC_OS_DEPLOYMENT_MIN_13_00)
+#define SANITIZER_INTERCEPT_GETSERVENT_R SI_GLIBC
+#define SANITIZER_INTERCEPT_GETSERVBYNAME_R SI_GLIBC
+#define SANITIZER_INTERCEPT_GETSERVBYPORT_R SI_GLIBC
+
// This macro gives a way for downstream users to override the above
// interceptor macros irrespective of the platform they are on. They have
// to do two things:
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 67f00ff6f9e72..1f7e3d21b6a6f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -1509,6 +1509,15 @@ extern unsigned IOCTL_KIOCSOUND;
extern unsigned IOCTL_PIO_SCRNMAP;
#endif
+# if SANITIZER_GLIBC
+struct __sanitizer_servent {
+ char *s_name;
+ char **s_aliases;
+ int s_port;
+ char *s_proto;
+};
+# endif
+
extern const int si_SEGV_MAPERR;
extern const int si_SEGV_ACCERR;
} // namespace __sanitizer
>From 7871fb47f15f34b527be4e119be0a035e2e1a29e Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 28 Mar 2025 15:29:49 -0700
Subject: [PATCH 2/4] add test
Created using spr 1.3.4
---
.../TestCases/Linux/getservent_r.cpp | 29 +++++++++++++++++++
1 file changed, 29 insertions(+)
create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
new file mode 100644
index 0000000000000..a0444477a9ff0
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
@@ -0,0 +1,29 @@
+// RUN: %clangxx -O0 %s -o %t && %run %t
+
+// REQUIRES: glibc
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <netdb.h>
+
+int main(void) {
+ struct servent result_buf;
+ struct servent *result;
+ char buf[1024];
+ assert(getservent_r(&result_buf, buf, sizeof(buf), &result) == 0);
+ assert(result != nullptr);
+
+ // If these fail, check /etc/services if "ssh" exists. I picked this because
+ // it should exist everywhere, if it doesn't, I am sorry. Disable the test
+ // then please.
+ assert(getservbyname_r("ssh", nullptr, &result_buf, buf, sizeof(buf),
+ &result) == 0);
+ assert(result != nullptr);
+ assert(getservbyport_r(htons(22), nullptr, &result_buf, buf, sizeof(buf),
+ &result) == 0);
+ assert(result != nullptr);
+
+ assert(getservbyname_r("invalidhadfuiasdhi", nullptr, &result_buf, buf,
+ sizeof(buf), &result) == 0);
+ assert(result == nullptr);
+}
>From 3392ff361a2005e79ae42f5199625255df0a3690 Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Fri, 28 Mar 2025 16:50:17 -0700
Subject: [PATCH 3/4] better errors
Created using spr 1.3.4
---
.../TestCases/Linux/getservent_r.cpp | 25 +++++++++++++------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
index a0444477a9ff0..9f9a4544a3db1 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
@@ -4,26 +4,37 @@
#include <arpa/inet.h>
#include <assert.h>
+#include <errno.h>
#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void CheckResult(int ret) {
+ if (ret != 0) {
+ fprintf(stderr, "%s\n", strerror(errno));
+ abort();
+ }
+}
int main(void) {
struct servent result_buf;
struct servent *result;
char buf[1024];
- assert(getservent_r(&result_buf, buf, sizeof(buf), &result) == 0);
+ CheckResult(getservent_r(&result_buf, buf, sizeof(buf), &result));
assert(result != nullptr);
// If these fail, check /etc/services if "ssh" exists. I picked this because
// it should exist everywhere, if it doesn't, I am sorry. Disable the test
// then please.
- assert(getservbyname_r("ssh", nullptr, &result_buf, buf, sizeof(buf),
- &result) == 0);
+ CheckResult(
+ getservbyname_r("ssh", nullptr, &result_buf, buf, sizeof(buf), &result));
assert(result != nullptr);
- assert(getservbyport_r(htons(22), nullptr, &result_buf, buf, sizeof(buf),
- &result) == 0);
+ CheckResult(getservbyport_r(htons(22), nullptr, &result_buf, buf, sizeof(buf),
+ &result));
assert(result != nullptr);
- assert(getservbyname_r("invalidhadfuiasdhi", nullptr, &result_buf, buf,
- sizeof(buf), &result) == 0);
+ CheckResult(getservbyname_r("invalidhadfuiasdhi", nullptr, &result_buf, buf,
+ sizeof(buf), &result));
assert(result == nullptr);
}
>From 185bde8d101314e96393589311a1042d1179e97e Mon Sep 17 00:00:00 2001
From: Florian Mayer <fmayer at google.com>
Date: Mon, 31 Mar 2025 10:51:33 -0700
Subject: [PATCH 4/4] test update
Created using spr 1.3.4
---
.../test/sanitizer_common/TestCases/Linux/getservent_r.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
index 9f9a4544a3db1..73979ea1ecb5d 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getservent_r.cpp
@@ -12,7 +12,7 @@
void CheckResult(int ret) {
if (ret != 0) {
- fprintf(stderr, "%s\n", strerror(errno));
+ fprintf(stderr, "ERROR: %s\n", strerror(ret));
abort();
}
}
More information about the llvm-commits
mailing list