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;
}