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

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


Author: Michael Jones
Date: 2024-11-22T13:41:07-08:00
New Revision: 182f9aad8b8a7b0141180056b36bb5f633138eb1

URL: https://github.com/llvm/llvm-project/commit/182f9aad8b8a7b0141180056b36bb5f633138eb1
DIFF: https://github.com/llvm/llvm-project/commit/182f9aad8b8a7b0141180056b36bb5f633138eb1.diff

LOG: [libc] Fix unpoisoning for recvfrom (#117366)

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

Added: 
    

Modified: 
    libc/src/sys/socket/linux/recvfrom.cpp
    libc/src/sys/socket/recvfrom.h

Removed: 
    


################################################################################
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..5c12410dd4ea43 100644
--- a/libc/src/sys/socket/recvfrom.h
+++ b/libc/src/sys/socket/recvfrom.h
@@ -18,8 +18,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
-                 struct sockaddr *__restrict address,
-                 socklen_t *__restrict addrlen);
+                 sockaddr *__restrict src_addr, socklen_t *__restrict addrlen);
 
 } // namespace LIBC_NAMESPACE_DECL
 


        


More information about the libc-commits mailing list