[libc-commits] [libc] [libc] Fix unpoisoning for recvfrom (PR #117366)

via libc-commits libc-commits at lists.llvm.org
Fri Nov 22 11:31:13 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Michael Jones (michaelrj-google)

<details>
<summary>Changes</summary>

Turns out there were also errors in the recvfrom unpoisoning logic. This
patch fixes those.


---
Full diff: https://github.com/llvm/llvm-project/pull/117366.diff


2 Files Affected:

- (modified) libc/src/sys/socket/linux/recvfrom.cpp (+18-4) 
- (modified) libc/src/sys/socket/recvfrom.h (+1-1) 


``````````diff
diff --git a/libc/src/sys/socket/linux/recvfrom.cpp b/libc/src/sys/socket/linux/recvfrom.cpp
index a0f8278cd5deb4..574e65f64a54b0 100644
--- a/libc/src/sys/socket/linux/recvfrom.cpp
+++ b/libc/src/sys/socket/linux/recvfrom.cpp
@@ -23,17 +23,26 @@ namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
                    (int sockfd, void *buf, size_t len, int flags,
-                    struct sockaddr *__restrict dest_addr,
+                    sockaddr *__restrict src_addr,
                     socklen_t *__restrict addrlen)) {
+  // addrlen is a value-result argument. If it's not null, it passes the max
+  // size of the buffer src_addr to the syscall. After the syscall, it's updated
+  // to the actual size of the source address. This may be larger than the
+  // buffer, in which case the buffer contains a truncated result.
+  size_t srcaddr_sz;
+  if (src_addr)
+    srcaddr_sz = *addrlen;
+  (void)srcaddr_sz; // prevent "set but not used" warning
+
 #ifdef SYS_recvfrom
   ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
-      SYS_recvfrom, sockfd, buf, len, flags, dest_addr, addrlen);
+      SYS_recvfrom, sockfd, buf, len, flags, src_addr, addrlen);
 #elif defined(SYS_socketcall)
   unsigned long sockcall_args[6] = {static_cast<unsigned long>(sockfd),
                                     reinterpret_cast<unsigned long>(buf),
                                     static_cast<unsigned long>(len),
                                     static_cast<unsigned long>(flags),
-                                    reinterpret_cast<unsigned long>(dest_addr),
+                                    reinterpret_cast<unsigned long>(src_addr),
                                     static_cast<unsigned long>(addrlen)};
   ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(
       SYS_socketcall, SYS_RECVFROM, sockcall_args);
@@ -46,8 +55,13 @@ LLVM_LIBC_FUNCTION(ssize_t, recvfrom,
   }
 
   MSAN_UNPOISON(buf, ret);
-  MSAN_UNPOISON(addrlen, sizeof(socklen_t));
 
+  if (src_addr) {
+    size_t min_src_addr_size = (*addrlen < srcaddr_sz) ? *addrlen : srcaddr_sz;
+    (void)min_src_addr_size; // prevent "set but not used" warning
+
+    MSAN_UNPOISON(src_addr, min_src_addr_size);
+  }
   return ret;
 }
 
diff --git a/libc/src/sys/socket/recvfrom.h b/libc/src/sys/socket/recvfrom.h
index 14869802e72563..15d70d6d010f06 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -18,7 +18,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
-                 struct sockaddr *__restrict address,
+                 struct sockaddr *__restrict src_addr,
                  socklen_t *__restrict addrlen);
 
 } // namespace LIBC_NAMESPACE_DECL

``````````

</details>


https://github.com/llvm/llvm-project/pull/117366


More information about the libc-commits mailing list