[compiler-rt] [compiler-rt][sanitizer-common] intercept getaddrinfo_a for Linux. (PR #123167)

David CARLIER via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 16 04:29:43 PST 2025


https://github.com/devnexen updated https://github.com/llvm/llvm-project/pull/123167

>From 5cd7b8bf5c503e02d879770e4774c987da227679 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Thu, 16 Jan 2025 06:56:14 +0000
Subject: [PATCH] [compiler-rt][sanitizer-common] intercept getaddrinfo_a for
 Linux.

---
 .../sanitizer_common_interceptors.inc         | 53 +++++++++++++++++++
 .../sanitizer_platform_interceptors.h         |  1 +
 .../sanitizer_platform_limits_posix.cpp       |  6 +++
 .../sanitizer_platform_limits_posix.h         | 10 ++++
 compiler-rt/test/msan/Linux/getaddrinfo_a.cpp | 32 +++++++++++
 5 files changed, 102 insertions(+)
 create mode 100644 compiler-rt/test/msan/Linux/getaddrinfo_a.cpp

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 24a8a2d4dc55b4..5ba5f254be47fa 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -10263,6 +10263,58 @@ INTERCEPTOR(SSIZE_T, freadlink, int fd, char *buf, SIZE_T bufsiz) {
 #  define INIT_FREADLINK
 #endif
 
+#if SANITIZER_INTERCEPT_GETADDRINFO_A
+INTERCEPTOR(int, getaddrinfo_a, int mode, struct __sanitizer_gaicb *list,
+            int num, void *sevp) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo_a, mode, list, num, sevp);
+  if (sevp)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, sevp, struct_sigevent_sz);
+  if (list) {
+    for (int i = 0; i < num; i++) {
+      struct __sanitizer_gaicb *cb = list[i];
+      COMMON_INTERCEPTOR_READ_RANGE(ctx, cb, sizeof(__sanitizer_gaicb));
+      if (cb->ar_name)
+        COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_name,
+                                      internal_strlen(cb->ar_name) + 1);
+      if (cb->ar_service)
+        COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_service,
+                                      internal_strlen(cb->ar_service) + 1);
+      if (cb->ar_request) {
+        COMMON_INTERCEPTOR_READ_RANGE(ctx, cb->ar_request,
+                                      sizeof(__sanitizer_addrinfo));
+      }
+    }
+  }
+
+  int res = REAL(getaddrinfo_a)(mode, list, num, sevp);
+  if (res == 0 && list) {
+    for (int i = 0; i < num; i++) {
+      struct __sanitizer_addrinfo *result = list[i]->ar_result;
+      if (result) {
+        while (result) {
+          COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result,
+                                         sizeof(__sanitizer_addrinfo));
+          if (result->ai_addr)
+            COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result->ai_addr,
+                                           result->ai_addrlen);
+          if (result->ai_canonname)
+            COMMON_INTERCEPTOR_WRITE_RANGE(
+                ctx, result->ai_canonname,
+                internal_strlen(result->ai_canonname) + 1);
+          result = result->ai_next;
+        }
+      }
+    }
+  }
+
+  return res;
+}
+#  define INIT_GETADDRINFO_A COMMON_INTERCEPT_FUNCTION(getaddrinfo_a)
+#else
+#  define INIT_GETADDRINFO_A
+#endif
+
 #include "sanitizer_common_interceptors_netbsd_compat.inc"
 
 namespace __sanitizer {
@@ -10585,6 +10637,7 @@ static void InitializeCommonInterceptors() {
   INIT_PREADV2;
   INIT_PWRITEV2;
   INIT_FREADLINK;
+  INIT_GETADDRINFO_A;
 
   INIT___PRINTF_CHK;
 }
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index febd233bb1e3c0..4f8bde076f8483 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -640,6 +640,7 @@ 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_GETADDRINFO_A SI_LINUX
 // 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.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
index ddd67cb43524d4..bed311608daeb8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -1172,6 +1172,12 @@ CHECK_TYPE_SIZE(__kernel_old_gid_t);
 CHECK_TYPE_SIZE(__kernel_off_t);
 CHECK_TYPE_SIZE(__kernel_loff_t);
 CHECK_TYPE_SIZE(__kernel_fd_set);
+
+CHECK_TYPE_SIZE(gaicb);
+CHECK_SIZE_AND_OFFSET(gaicb, ar_name);
+CHECK_SIZE_AND_OFFSET(gaicb, ar_service);
+CHECK_SIZE_AND_OFFSET(gaicb, ar_request);
+CHECK_SIZE_AND_OFFSET(gaicb, ar_result);
 #endif
 
 #if !SANITIZER_ANDROID
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 7e62dc0e0523ec..bafbf5d4b5545f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -788,6 +788,16 @@ struct __sanitizer_addrinfo {
   struct __sanitizer_addrinfo *ai_next;
 };
 
+#  if SANITIZER_LINUX
+struct __sanitizer_gaicb {
+  const char *ar_name;
+  const char *ar_service;
+  const struct __sanitizer_addrinfo *ar_request;
+  struct __sanitizer_addrinfo *ar_result;
+  int __pad[6];
+};
+#  endif
+
 struct __sanitizer_hostent {
   char *h_name;
   char **h_aliases;
diff --git a/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp b/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp
new file mode 100644
index 00000000000000..1902057fcdcce8
--- /dev/null
+++ b/compiler-rt/test/msan/Linux/getaddrinfo_a.cpp
@@ -0,0 +1,32 @@
+// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out && FileCheck %s < %t.out
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+int main(void) {
+  const int nm = 4;
+  struct gaicb *list[nm];
+
+  for (auto i = 0; i < nm; i++) {
+    list[i] = (struct gaicb *)malloc(sizeof(struct gaicb));
+    if (i % 2)
+      memset(list[i], 0, sizeof(struct gaicb));
+    list[i]->ar_name = "name";
+  }
+
+  int res = getaddrinfo_a(GAI_WAIT, list, nm, NULL);
+  for (auto i = 0; i < nm; i++) {
+    // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value
+    // CHECK: {{#0 .* in main.*getaddrinfo_a.cpp:25}}
+    for (auto it = list[i]->ar_result; it; it = it->ai_next) {
+      auto name = it->ai_canonname;
+    }
+
+    free(list[i]);
+  }
+  return 0;
+}



More information about the llvm-commits mailing list