Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package valkey for openSUSE:Factory checked in at 2025-07-18 15:57:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/valkey (Old) and /work/SRC/openSUSE:Factory/.valkey.new.8875 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "valkey" Fri Jul 18 15:57:44 2025 rev:14 rq:1294199 version:8.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/valkey/valkey.changes 2025-06-13 18:42:25.715460982 +0200 +++ /work/SRC/openSUSE:Factory/.valkey.new.8875/valkey.changes 2025-07-18 15:58:31.478456963 +0200 @@ -1,0 +2,11 @@ +Tue Jul 15 21:47:08 UTC 2025 - Antonio Teixeira <antonio.teixe...@suse.com> + +- Update to 8.1.3: + - Security fixes + * CVE-2025-32023 prevent out-of-bounds write during hyperloglog operations + (boo#1246059) + * CVE-2025-48367 retry accept on transient errors (#2315) (boo#1246058) + - Bug fixes + * Fix missing response when AUTH is errored inside a transaction (#2287) + +------------------------------------------------------------------- Old: ---- valkey-8.1.2.tar.gz New: ---- valkey-8.1.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ valkey.spec ++++++ --- /var/tmp/diff_new_pack.xQJkTY/_old 2025-07-18 15:58:32.054481026 +0200 +++ /var/tmp/diff_new_pack.xQJkTY/_new 2025-07-18 15:58:32.058481193 +0200 @@ -26,7 +26,7 @@ %global make_flags CFLAGS="%{build_cflags}" DEBUG="" V="echo" PREFIX=%{buildroot}%{_prefix} BUILD_WITH_SYSTEMD=yes BUILD_TLS=yes Name: valkey -Version: 8.1.2 +Version: 8.1.3 Release: 0 Summary: Persistent key-value database License: BSD-3-Clause ++++++ valkey-8.1.2.tar.gz -> valkey-8.1.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/00-RELEASENOTES new/valkey-8.1.3/00-RELEASENOTES --- old/valkey-8.1.2/00-RELEASENOTES 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/00-RELEASENOTES 2025-07-07 09:18:20.000000000 +0200 @@ -10,6 +10,22 @@ -------------------------------------------------------------------------------- ================================================================================ +Valkey 8.1.3 - Released Sun 07 July 2025 +================================================================================ + +Upgrade urgency SECURITY: This release includes security fixes we recommend you +apply as soon as possible. + +Bug fixes +========= +* Fix missing response when AUTH is errored inside a transaction (#2287) + +Security fixes +============== +* CVE-2025-32023 prevent out-of-bounds write during hyperloglog operations (#2146) +* CVE-2025-48367 retry accept on transient errors (#2315) + +================================================================================ Valkey 8.1.2 - Released Wed 11 June 2025 ================================================================================ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/acl.c new/valkey-8.1.3/src/acl.c --- old/valkey-8.1.2/src/acl.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/acl.c 2025-07-07 09:18:20.000000000 +0200 @@ -1439,7 +1439,12 @@ /* If `err` is provided, this is added as an error reply to the client. * Otherwise, the standard Auth error is added as a reply. */ void addAuthErrReply(client *c, robj *err) { - if (clientHasPendingReplies(c)) return; + /* Note that a module auth can add reply in its callback, or not + * add reply and just return an error robj in its callback. So in + * here, we use buffered_reply flag to determine if auth command + * has already had a reply added. */ + if (c->flag.buffered_reply) return; + if (!err) { addReplyError(c, "-WRONGPASS invalid username-password pair or user is disabled."); return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/anet.c new/valkey-8.1.3/src/anet.c --- old/valkey-8.1.2/src/anet.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/anet.c 2025-07-07 09:18:20.000000000 +0200 @@ -639,6 +639,37 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/anet.h new/valkey-8.1.3/src/anet.h --- old/valkey-8.1.2/src/anet.h 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/anet.h 2025-07-07 09:18:20.000000000 +0200 @@ -74,5 +74,6 @@ int anetSetSockMarkId(char *err, int fd, uint32_t id); int anetGetError(int fd); int anetIsFifo(char *filepath); +int anetRetryAcceptOnError(int err); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/cluster_legacy.c new/valkey-8.1.3/src/cluster_legacy.c --- old/valkey-8.1.2/src/cluster_legacy.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/cluster_legacy.c 2025-07-07 09:18:20.000000000 +0200 @@ -1504,6 +1504,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/hyperloglog.c new/valkey-8.1.3/src/hyperloglog.c --- old/valkey-8.1.2/src/hyperloglog.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/hyperloglog.c 2025-07-07 09:18:20.000000000 +0200 @@ -602,6 +602,7 @@ 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; @@ -621,16 +622,27 @@ 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++; @@ -641,7 +653,7 @@ /* 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; } @@ -938,27 +950,40 @@ 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 ============================== @@ -1230,22 +1255,34 @@ } 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++; @@ -1253,7 +1290,7 @@ p++; } } - if (i != HLL_REGISTERS) return C_ERR; + if (!valid || i != HLL_REGISTERS) return C_ERR; } return C_OK; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/socket.c new/valkey-8.1.3/src/socket.c --- old/valkey-8.1.2/src/socket.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/socket.c 2025-07-07 09:18:20.000000000 +0200 @@ -322,6 +322,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/tls.c new/valkey-8.1.3/src/tls.c --- old/valkey-8.1.2/src/tls.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/tls.c 2025-07-07 09:18:20.000000000 +0200 @@ -788,6 +788,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/unix.c new/valkey-8.1.3/src/unix.c --- old/valkey-8.1.2/src/unix.c 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/unix.c 2025-07-07 09:18:20.000000000 +0200 @@ -107,6 +107,7 @@ 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; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/src/version.h new/valkey-8.1.3/src/version.h --- old/valkey-8.1.2/src/version.h 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/src/version.h 2025-07-07 09:18:20.000000000 +0200 @@ -4,8 +4,8 @@ * similar. */ #define SERVER_NAME "valkey" #define SERVER_TITLE "Valkey" -#define VALKEY_VERSION "8.1.2" -#define VALKEY_VERSION_NUM 0x00080102 +#define VALKEY_VERSION "8.1.3" +#define VALKEY_VERSION_NUM 0x00080103 /* The release stage is used in order to provide release status information. * In unstable branch the status is always "dev". * During release process the status will be set to rc1,rc2...rcN. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/tests/unit/hyperloglog.tcl new/valkey-8.1.3/tests/unit/hyperloglog.tcl --- old/valkey-8.1.2/tests/unit/hyperloglog.tcl 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/tests/unit/hyperloglog.tcl 2025-07-07 09:18:20.000000000 +0200 @@ -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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/valkey-8.1.2/tests/unit/multi.tcl new/valkey-8.1.3/tests/unit/multi.tcl --- old/valkey-8.1.2/tests/unit/multi.tcl 2025-06-11 22:15:00.000000000 +0200 +++ new/valkey-8.1.3/tests/unit/multi.tcl 2025-07-07 09:18:20.000000000 +0200 @@ -901,6 +901,13 @@ r flushall r ping } + + test "AUTH errored inside MULTI will add the reply" { + r config set requirepass "" + r multi + r auth no-user foobar + assert_error {WRONGPASS invalid username-password pair or user is disabled.} {r exec} + } } start_server {overrides {appendonly {yes} appendfilename {appendonly.aof} appendfsync always} tags {external:skip}} {