mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-07-12 18:59:50 +03:00
main/valkey: patch CVE-2025-32023 & CVE-2025-48367
This commit is contained in:
parent
db64a7a0c8
commit
717c26d65a
3 changed files with 313 additions and 1 deletions
|
@ -4,7 +4,7 @@
|
|||
# Maintainer: Jakub Jirutka <jakub@jirutka.cz>
|
||||
pkgname=valkey
|
||||
pkgver=8.1.1
|
||||
pkgrel=1
|
||||
pkgrel=2
|
||||
pkgdesc="Open source high-performance key/value datastore (fork of Redis)"
|
||||
url="https://valkey.io/"
|
||||
arch="all"
|
||||
|
@ -32,9 +32,14 @@ source="https://github.com/valkey-io/valkey/archive/$pkgver/valkey-$pkgver.tar.g
|
|||
$pkgname-sentinel.initd
|
||||
$pkgname-sentinel.confd
|
||||
CVE-2025-27151.patch
|
||||
CVE-2025-32023.patch
|
||||
CVE-2025-48367.patch
|
||||
"
|
||||
|
||||
# secfixes:
|
||||
# 8.1.1-r2:
|
||||
# - CVE-2025-32023
|
||||
# - CVE-2025-48367
|
||||
# 8.1.1-r1:
|
||||
# - CVE-2025-27151
|
||||
# 7.2.9-r0:
|
||||
|
@ -114,4 +119,6 @@ d0311d2bfade7efbfa2bdcc6c74e8e8a151c09c627e30f5cea1826155dcb4f7ca4c1d35aba26bcce
|
|||
dd407cb4047524114b4814a28993978acbe300989acc466ec3809171bf19a1e0562756f7b5954981a087a37437c2c281e4a3667d361cfa8873d1c20d1b900632 valkey-sentinel.initd
|
||||
926316561f0802b577caee03e7bccc5538dc8270095df95853549fdd519fac8d0e89bc3e563cdba2d7ec0dfe10db5e50b95859549597beec894c820abfdbecee valkey-sentinel.confd
|
||||
bc769dd0b5b30e657e176ddde4836ac1781a9cf9caccf19d635bf223ac58889aa5f7335b11f542f9240ab177f7c221651394584255eb4857b780e8a1d3ce45ea CVE-2025-27151.patch
|
||||
c5d9be725aaaa0e49590d91a7c6ad55d409cf75a981ce017f411627c5c79fda1812fa0f4de522842aaef26f9cf75d33fb3afe652354c36e3e41a86a06d67e575 CVE-2025-32023.patch
|
||||
e990ed04b6ba14f92335cf559f759e7f52bae51e037f3df2275408d5d4c10b5a18cc18aba8ea1939f28007a9a9ac2f3063b98eaf4d92c4959d7c5d8a836eb15e CVE-2025-48367.patch
|
||||
"
|
||||
|
|
186
main/valkey/CVE-2025-32023.patch
Normal file
186
main/valkey/CVE-2025-32023.patch
Normal file
|
@ -0,0 +1,186 @@
|
|||
Patch-Source: https://github.com/valkey-io/valkey/commit/20f5199d96baf0c64bd4e7d042b6274c4e773bcb
|
||||
---
|
||||
From 20f5199d96baf0c64bd4e7d042b6274c4e773bcb Mon Sep 17 00:00:00 2001
|
||||
From: Ran Shidlansik <ranshid@amazon.com>
|
||||
Date: Sun, 6 Jul 2025 23:20:32 +0300
|
||||
Subject: [PATCH] Apply fixed for CVE-2025-32023 (#2314)
|
||||
|
||||
Signed-off-by: Madelyn Olson <madelyneolson@gmail.com>
|
||||
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
|
||||
---
|
||||
src/hyperloglog.c | 47 ++++++++++++++++++++++++++++++++++----
|
||||
tests/unit/hyperloglog.tcl | 26 +++++++++++++++++++++
|
||||
2 files changed, 68 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/hyperloglog.c b/src/hyperloglog.c
|
||||
index 910e3ef6bb..28c0153dc3 100644
|
||||
--- a/src/hyperloglog.c
|
||||
+++ b/src/hyperloglog.c
|
||||
@@ -619,6 +619,7 @@ int hllSparseToDense(robj *o) {
|
||||
struct hllhdr *hdr, *oldhdr = (struct hllhdr *)sparse;
|
||||
int idx = 0, runlen, regval;
|
||||
uint8_t *p = (uint8_t *)sparse, *end = p + sdslen(sparse);
|
||||
+ int valid = 1;
|
||||
|
||||
/* If the representation is already the right one return ASAP. */
|
||||
hdr = (struct hllhdr *)sparse;
|
||||
@@ -638,16 +639,27 @@ int hllSparseToDense(robj *o) {
|
||||
while (p < end) {
|
||||
if (HLL_SPARSE_IS_ZERO(p)) {
|
||||
runlen = HLL_SPARSE_ZERO_LEN(p);
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
idx += runlen;
|
||||
p++;
|
||||
} else if (HLL_SPARSE_IS_XZERO(p)) {
|
||||
runlen = HLL_SPARSE_XZERO_LEN(p);
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
idx += runlen;
|
||||
p += 2;
|
||||
} else {
|
||||
runlen = HLL_SPARSE_VAL_LEN(p);
|
||||
regval = HLL_SPARSE_VAL_VALUE(p);
|
||||
- if ((runlen + idx) > HLL_REGISTERS) break; /* Overflow. */
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
while (runlen--) {
|
||||
HLL_DENSE_SET_REGISTER(hdr->registers, idx, regval);
|
||||
idx++;
|
||||
@@ -658,7 +670,7 @@ int hllSparseToDense(robj *o) {
|
||||
|
||||
/* If the sparse representation was valid, we expect to find idx
|
||||
* set to HLL_REGISTERS. */
|
||||
- if (idx != HLL_REGISTERS) {
|
||||
+ if (!valid || idx != HLL_REGISTERS) {
|
||||
sdsfree(dense);
|
||||
return C_ERR;
|
||||
}
|
||||
@@ -955,27 +967,40 @@ int hllSparseAdd(robj *o, unsigned char *ele, size_t elesize) {
|
||||
void hllSparseRegHisto(uint8_t *sparse, int sparselen, int *invalid, int *reghisto) {
|
||||
int idx = 0, runlen, regval;
|
||||
uint8_t *end = sparse + sparselen, *p = sparse;
|
||||
+ int valid = 1;
|
||||
|
||||
while (p < end) {
|
||||
if (HLL_SPARSE_IS_ZERO(p)) {
|
||||
runlen = HLL_SPARSE_ZERO_LEN(p);
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
idx += runlen;
|
||||
reghisto[0] += runlen;
|
||||
p++;
|
||||
} else if (HLL_SPARSE_IS_XZERO(p)) {
|
||||
runlen = HLL_SPARSE_XZERO_LEN(p);
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
idx += runlen;
|
||||
reghisto[0] += runlen;
|
||||
p += 2;
|
||||
} else {
|
||||
runlen = HLL_SPARSE_VAL_LEN(p);
|
||||
regval = HLL_SPARSE_VAL_VALUE(p);
|
||||
+ if ((runlen + idx) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
idx += runlen;
|
||||
reghisto[regval] += runlen;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
- if (idx != HLL_REGISTERS && invalid) *invalid = 1;
|
||||
+ if ((!valid || idx != HLL_REGISTERS) && invalid) *invalid = 1;
|
||||
}
|
||||
|
||||
/* ========================= HyperLogLog Count ==============================
|
||||
@@ -1344,22 +1369,34 @@ int hllMerge(uint8_t *max, robj *hll) {
|
||||
} else {
|
||||
uint8_t *p = hll->ptr, *end = p + sdslen(hll->ptr);
|
||||
long runlen, regval;
|
||||
+ int valid = 1;
|
||||
|
||||
p += HLL_HDR_SIZE;
|
||||
i = 0;
|
||||
while (p < end) {
|
||||
if (HLL_SPARSE_IS_ZERO(p)) {
|
||||
runlen = HLL_SPARSE_ZERO_LEN(p);
|
||||
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
i += runlen;
|
||||
p++;
|
||||
} else if (HLL_SPARSE_IS_XZERO(p)) {
|
||||
runlen = HLL_SPARSE_XZERO_LEN(p);
|
||||
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
i += runlen;
|
||||
p += 2;
|
||||
} else {
|
||||
runlen = HLL_SPARSE_VAL_LEN(p);
|
||||
regval = HLL_SPARSE_VAL_VALUE(p);
|
||||
- if ((runlen + i) > HLL_REGISTERS) break; /* Overflow. */
|
||||
+ if ((runlen + i) > HLL_REGISTERS) { /* Overflow. */
|
||||
+ valid = 0;
|
||||
+ break;
|
||||
+ }
|
||||
while (runlen--) {
|
||||
if (regval > max[i]) max[i] = regval;
|
||||
i++;
|
||||
@@ -1367,7 +1404,7 @@ int hllMerge(uint8_t *max, robj *hll) {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
- if (i != HLL_REGISTERS) return C_ERR;
|
||||
+ if (!valid || i != HLL_REGISTERS) return C_ERR;
|
||||
}
|
||||
return C_OK;
|
||||
}
|
||||
diff --git a/tests/unit/hyperloglog.tcl b/tests/unit/hyperloglog.tcl
|
||||
index 765d5e0bdd..ca46a407bd 100644
|
||||
--- a/tests/unit/hyperloglog.tcl
|
||||
+++ b/tests/unit/hyperloglog.tcl
|
||||
@@ -1,4 +1,30 @@
|
||||
start_server {tags {"hll"}} {
|
||||
+ test {CVE-2025-32023: Sparse HLL XZERO overflow triggers crash} {
|
||||
+ # Build a valid HLL header for sparse encoding
|
||||
+ set hll [binary format cccc 72 89 76 76] ; # "HYLL"
|
||||
+ append hll [binary format cccc 1 0 0 0] ; # encoding=sparse, 3 reserved
|
||||
+ append hll [binary format cccccccc 0 0 0 0 0 0 0 0] ; # cached cardinality
|
||||
+
|
||||
+ # We need alternating XZERO and ZERO opcodes to build up a large enough
|
||||
+ # HyperLogLog value that will overflow the runlength.
|
||||
+ # 0x7f 0xff is the XZERO opcode that sets the index to 16384.
|
||||
+ # 0x3f is the ZERO opcode that sets the index to 256.
|
||||
+ # We repeat this pattern at least 33554432 times to overflow the runlength,
|
||||
+ # 50331648 is just 33554432 * 1.5, which is just a round number.
|
||||
+ append hll [string repeat [binary format ccc 0x7f 0xff 0x3f] 50331648]
|
||||
+
|
||||
+ # We need an actual value at the end to trigger the out of bounds write
|
||||
+ append hll [binary format c 0x80]
|
||||
+
|
||||
+ # Set the raw value into the key
|
||||
+ r set hll_overflow $hll
|
||||
+ r pfadd hll_merge_source hi
|
||||
+
|
||||
+ # Test pfadd and pfmerge, these used to crash but now error
|
||||
+ assert_error {*INVALIDOBJ*} {r pfmerge fail_target hll_overflow hll_merge_source}
|
||||
+ assert_error {*INVALIDOBJ*} {r pfadd hll_overflow foo}
|
||||
+ } {} {large-memory}
|
||||
+
|
||||
test {HyperLogLog self test passes} {
|
||||
catch {r pfselftest} e
|
||||
set e
|
119
main/valkey/CVE-2025-48367.patch
Normal file
119
main/valkey/CVE-2025-48367.patch
Normal file
|
@ -0,0 +1,119 @@
|
|||
Patch-Source: https://github.com/valkey-io/valkey/commit/cb10d9d78f35945b667e46967b3980e89954d73b
|
||||
---
|
||||
From cb10d9d78f35945b667e46967b3980e89954d73b 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 5e970e2cf2..8bc1626966 100644
|
||||
--- a/src/anet.c
|
||||
+++ b/src/anet.c
|
||||
@@ -659,6 +659,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 f5bca1acab..79a4ecebfb 100644
|
||||
--- a/src/anet.h
|
||||
+++ b/src/anet.h
|
||||
@@ -74,6 +74,7 @@ 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);
|
||||
|
||||
static inline int anetHasMptcp(void) {
|
||||
#ifdef IPPROTO_MPTCP
|
||||
diff --git a/src/cluster_legacy.c b/src/cluster_legacy.c
|
||||
index 82a2fad21b..236f58639e 100644
|
||||
--- a/src/cluster_legacy.c
|
||||
+++ b/src/cluster_legacy.c
|
||||
@@ -1585,6 +1585,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 fba18f2161..5a1ca11f75 100644
|
||||
--- a/src/socket.c
|
||||
+++ b/src/socket.c
|
||||
@@ -323,6 +323,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 e5af01b2fa..5360212b63 100644
|
||||
--- a/src/tls.c
|
||||
+++ b/src/tls.c
|
||||
@@ -791,6 +791,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 58a07e50a4..bc45e45193 100644
|
||||
--- a/src/unix.c
|
||||
+++ b/src/unix.c
|
||||
@@ -118,6 +118,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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue