File CVE-2025-48367.patch of Package valkey.39739

From 25d3c19ffac60cc245610386c111299844cb02f9 Mon Sep 17 00:00:00 2001
From: Ran Shidlansik <ranshid@amazon.com>
Date: Mon, 7 Jul 2025 00:40:08 +0300
Subject: [PATCH] retry accept on transient errors (CVE-2025-48367) (#2315)

Signed-off-by: Ran Shidlansik <ranshid@amazon.com>
---
 src/anet.c           | 31 +++++++++++++++++++++++++++++++
 src/anet.h           |  1 +
 src/cluster_legacy.c |  1 +
 src/socket.c         |  1 +
 src/tls.c            |  1 +
 src/unix.c           |  1 +
 6 files changed, 36 insertions(+)

diff --git a/src/anet.c b/src/anet.c
index d4ac698982..24a6f4c695 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -614,6 +614,37 @@ int anetUnixServer(char *err, char *path, mode_t perm, int backlog, char *group)
     return s;
 }
 
+/* For some error cases indicates transient errors and accept can be retried
+ * in order to serve other pending connections. This function should be called with the last errno,
+ * right after anetTcpaccept or anetUnixAccept returned an error in order to retry them. */
+int anetRetryAcceptOnError(int err) {
+    /* This is a transient error which can happen, for example, when
+     * a client initiates a TCP handshake (SYN),
+     * the server receives and queues it in the pending connections queue (the SYN queue),
+     * but before accept() is called, the connection is aborted.
+     * in such cases we can continue accepting other connections. ß*/
+    if (err == ECONNABORTED)
+        return 1;
+
+#if defined(__linux__)
+    /* https://www.man7.org/linux/man-pages/man2/accept4.2 suggests that:
+     * Linux accept() (and accept4()) passes already-pending network
+       errors on the new socket as an error code from accept().  This
+       behavior differs from other BSD socket implementations.  For
+       reliable operation the application should detect the network
+       errors defined for the protocol after accept() and treat them like
+       EAGAIN by retrying.  In the case of TCP/IP, these are ENETDOWN,
+       EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP,
+       and ENETUNREACH. */
+    if (err == ENETDOWN || err == EPROTO || err == ENOPROTOOPT ||
+        err == EHOSTDOWN || err == ENONET || err == EHOSTUNREACH ||
+        err == EOPNOTSUPP || err == ENETUNREACH) {
+        return 1;
+    }
+#endif
+    return 0;
+}
+
 /* Accept a connection and also make sure the socket is non-blocking, and CLOEXEC.
  * returns the new socket FD, or -1 on error. */
 static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) {
diff --git a/src/anet.h b/src/anet.h
index ab32f72e4b..9c3b6b4d05 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -73,5 +73,6 @@ int anetPipe(int fds[2], int read_flags, int write_flags);
 int anetSetSockMarkId(char *err, int fd, uint32_t id);
 int anetGetError(int fd);
 int anetIsFifo(char *filepath);
+int anetRetryAcceptOnError(int err);
 
 #endif
diff --git a/src/cluster_legacy.c b/src/cluster_legacy.c
index d397855c3f..087bf3758d 100644
--- a/src/cluster_legacy.c
+++ b/src/cluster_legacy.c
@@ -1443,6 +1443,7 @@ void clusterAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask) {
     while (max--) {
         cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
         if (cfd == ANET_ERR) {
+            if (anetRetryAcceptOnError(errno)) continue;
             if (errno != EWOULDBLOCK) serverLog(LL_VERBOSE, "Error accepting cluster node: %s", server.neterr);
             return;
         }
diff --git a/src/socket.c b/src/socket.c
index 7344d66ad8..d92a0de3ba 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -312,6 +312,7 @@ static void connSocketAcceptHandler(aeEventLoop *el, int fd, void *privdata, int
     while (max--) {
         cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
         if (cfd == ANET_ERR) {
+            if (anetRetryAcceptOnError(errno)) continue;
             if (errno != EWOULDBLOCK) serverLog(LL_WARNING, "Accepting client connection: %s", server.neterr);
             return;
         }
diff --git a/src/tls.c b/src/tls.c
index 1ac8e19bfe..a1f101d9c5 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -780,6 +780,7 @@ static void tlsAcceptHandler(aeEventLoop *el, int fd, void *privdata, int mask)
     while (max--) {
         cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport);
         if (cfd == ANET_ERR) {
+            if (anetRetryAcceptOnError(errno)) continue;
             if (errno != EWOULDBLOCK) serverLog(LL_WARNING, "Accepting client connection: %s", server.neterr);
             return;
         }
diff --git a/src/unix.c b/src/unix.c
index ddfd73465a..5d386522e0 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -102,6 +102,7 @@ static void connUnixAcceptHandler(aeEventLoop *el, int fd, void *privdata, int m
     while (max--) {
         cfd = anetUnixAccept(server.neterr, fd);
         if (cfd == ANET_ERR) {
+            if (anetRetryAcceptOnError(errno)) continue;
             if (errno != EWOULDBLOCK) serverLog(LL_WARNING, "Accepting client connection: %s", server.neterr);
             return;
         }
openSUSE Build Service is sponsored by