[CLSA-2026:1791526825] Fix CVE(s): CVE-2025-1218
Type:
security
Severity:
Important
Release date:
2026-10-09 06:20:36 UTC
Description:
* SECURITY UPDATE: various out-of-bounds reads in the mysqlnd wire-protocol parser - debian/patches/php-5.6-CVE-2025-1218.patch: backport upstream commit 114dbb74368e (GHSA-r6x9-5r99-36j7) across ext/mysqlnd/ mysqlnd_wireprotocol.c, mysqlnd_wireprotocol.h, mysqlnd_ps_codec.c and mysqlnd_ps.c. The parser read fields out of a server packet before checking that the packet still held enough bytes, so a malicious or compromised MySQL server could make the client read past the end of the packet buffer. BAIL_IF_NO_MORE_DATA, which noticed an over-read only after it had happened, is replaced by the BAIL_PREMATURE_END / BAIL_IF_NOT_ENOUGH_DATA_EX family, which refuses the read up front; php_mysqlnd_net_field_length() and its _ll() variant take the remaining packet size and report MYSQLND_INVALID_NET_FIELD_LENGTH instead of blindly consuming 2, 3 or 8 bytes; the server version, the auth-switch plugin name in the auth-response, change-user and cached-sha2-result packets are located with memchr() over the remaining bytes instead of strdup()/strlen(); the greeting's fixed 31-byte block, its extended scramble, the result-set field metadata lengths, the in-row EOF marker and the text-protocol field lengths all gain real bounds checks; and ps_fetch_time/date/datetime reject a declared length too short for the fixed offsets they read. - This branch needs the CVE-2024-8929 backport as a prerequisite: it is what supplies the three mysqlnd_ps_codec.c over-read helpers and the packet_end guard that the upstream change builds on, none of which are in the 5.6.40 tarball. - php-5.6.40-caching-sha2-password.patch introduces php_mysqlnd_cached_sha2_result_read() on this branch, so both of its over-reads are live here and are fixed. Its auth-switch branch did mnd_pestrdup() plus strlen() straight off a 2048-byte stack buffer that nothing NUL-terminates, and handed the result to the caller; and the second response-code byte was read before its bounds check, one byte past a one-byte packet. For that reason this patch is applied after php-5.6.40-caching-sha2-password.patch rather than with the other CVE patches. - The greeting's authentication plugin name is still read with an unbounded estrdup() on 5.6.40, so the bounded form php-8.1.34 carries is included as a prerequisite before upstream's removal of the "buf[header.size] = 0" hack, which would otherwise have converted a terminated read into an unbounded one. - Not every hunk is a memory-safety fix, and the ones that are not are not presented as such: php_mysqlnd_prepare_read() and php_mysqlnd_sha256_pk_request_response_read() are hardening - behind the existing PREPARE_RESPONSE_SIZE gate the new prepare_read checks cannot fire - and the mysqlnd_ps.c hunk is a leak fix on the newly reachable failure path, releasing the connection reference and the execute command buffer that the following memset() would otherwise drop. - Upstream's guard around MARIADB_RPL_VERSION_HACK has no target here; that macro does not exist on this branch. Upstream's rejection of any "def" value in the result-set field packet is also not taken, because COM_FIELD_LIST is still supported on 5.6 and that change would break it; the existing def bounds check is kept and only given the remaining size. - Upstream's 38 regression tests are NOT carried. They are written against the dynamic-port fake server upstream added in the same commit: run_fake_server_in_background() takes no port, the test reads getPort(), and the expectation asserts the address the server printed. The harness this branch has, ext/mysqli/tests/fake_server.inc from the CVE-2024-8929 backport, predates that API and binds a fixed port, so carrying the tests means rewriting all 38 to hardcode a port and to drop the address assertion. Nothing would run them either way: php56.spec gates its suite behind the runselftest toggle, which defaults to 0, and debian/rules has no test target. They were run locally instead, on a tree built from this repository's own patch series, first patched and then with only the C hunks of this patch reversed out and rebuilt: 32 of 38 pass patched, 0 fail; 8 of 38 pass unpatched, 24 fail. The 6 skips in both arms are the cached-sha2 and sha256-pk tests, which need ext/openssl - PHP 5.6's openssl extension does not compile against OpenSSL 3, so that build had no ext/openssl. - The same hunk also corrects that path's result free from mnd_efree() to upstream's php-7.0 form, mnd_pefree(stmt->result, stmt->result->persistent), since mysqlnd_result_init() allocates the result with mnd_pecalloc(..., persistent) and a persistent connection therefore gave the Zend allocator a malloc()ed block; before the change a hostile prepare over p:127.0.0.1 aborts with "zend_mm_heap corrupted" on a build with the Zend MM heap checks compiled in, after it the same run completes - Also fixes a pre-existing use-after-free on the row-reader failure path. The CVE-2024-8929 backport added error loops in the binary- and text-protocol row readers that zval_ptr_dtor() every field decoded so far and return FAIL without clearing the zvals, so the result set frees the same zvals again when it is torn down. The loops were already reachable before this change; the new too-short TIME/DATE/DATETIME check adds a second way in. All 2 sites now clear the zval after freeing it. Confirmed under AddressSanitizer with the Zend allocator disabled: heap-use-after-free in mysqlnd_result_buffered_zval free_result before, clean after, on both the three new short-length tests and the nine CVE-2024-8929 stmt-row tests. Upstream still carries the same loops unguarded in php-8.2.34 through php-8.5.11; php-8.1 is not affected. - The mysqlnd_ps.c hunk additionally releases the result's own connection reference on the prepare-EOF path. Before PHP 7.4 (upstream f365d0e00ed93b1c33e984ff3b4cc8677cbca193) free_result_contents() did not drop it, so that path leaked one reference. The sibling site in mysqlnd_stmt store_result() leaks the same reference but is not made reachable by this change and is left for a separate one. - CVE-2025-1218 * mysqlnd: initialise every pre-allocated row field before decoding - debian/patches/php-5.6.40-mysqlnd-rowp-init-fields.patch: the binary- and text-protocol row readers pre-allocate a zval per column with MAKE_STD_ZVAL(), which sets no type, and only type it when the decode loop reaches that column. The CVE-2024-8929 error paths abandon a row part-way, so every column past the failure point stays allocated but never typed, and the result set still frees the whole row at teardown - _zval_ptr_dtor() then branches on an uninitialised Z_TYPE. Each column is now ZVAL_NULL()ed at allocation. Confirmed with valgrind under USE_ZEND_ALLOC=0: the CVE-2024-8929 and CVE-2025-1218 stmt-row tests go from 1 uninitialised-value error to 0. PHP 5 only - from PHP 7 the row is a caller-owned array that mysqlnd_store_result() memset()s to zero. Kept separate from the CVE patch because the defect predates it and is reachable without it
CVEs fixed:
Updated packages:
  • alt-php56_5.6.40-149_amd64.deb
    sha:bcc0408ac19b19f613ccb3bbaa3043a2aaccec7b
  • alt-php56-bcmath_5.6.40-149_amd64.deb
    sha:69bf3424f0b7e810d502e5fa9df31ca7f8b01faa
  • alt-php56-cli_5.6.40-149_amd64.deb
    sha:bf8ce23ae553bed4a5a386fd7352ccbc3bc20d4b
  • alt-php56-common_5.6.40-149_amd64.deb
    sha:fe45de0b357381ee28202cb699d40e43fc4e7859
  • alt-php56-dba_5.6.40-149_amd64.deb
    sha:0fca6a14dc164051a3bc3996aac20be6336edb88
  • alt-php56-dbx_5.6.40-149_amd64.deb
    sha:0a07d62a16b69d928214587185ed41f1d06b259f
  • alt-php56-dev_5.6.40-149_amd64.deb
    sha:6f191b7655f3eeba7e22620a4f984eb86c186afd
  • alt-php56-enchant_5.6.40-149_amd64.deb
    sha:72eb7272727c6f619abdb46268c92824ca9f78fc
  • alt-php56-firebird_5.6.40-149_amd64.deb
    sha:f6234c9ee6470c21608962138c4c7eabc12d0317
  • alt-php56-gd_5.6.40-149_amd64.deb
    sha:7e3fc29bf45ada9c99fbfe817e412dd4ff299cb4
  • alt-php56-imap_5.6.40-149_amd64.deb
    sha:25f3074e98d3c2f3fe91fa9612dbaa0ea9d4baf2
  • alt-php56-intl_5.6.40-149_amd64.deb
    sha:a5efe23b94b1db5409d104a414d8e9066c8ebbf4
  • alt-php56-ldap_5.6.40-149_amd64.deb
    sha:d70a36bc1d497da15832c995de71e5c4bc6cba09
  • alt-php56-mbstring_5.6.40-149_amd64.deb
    sha:2a32dc6be2fc3a10eece5a6aac2d9e473a17a9bd
  • alt-php56-mcrypt_5.6.40-149_amd64.deb
    sha:1b21c0b29b70ac8fa68c5fbd001dea36faaf538c
  • alt-php56-mysqlnd_5.6.40-149_amd64.deb
    sha:8c60f0b2e20608e60913fdb76ff6e629784cb7b7
  • alt-php56-odbc_5.6.40-149_amd64.deb
    sha:dfb200d08aca15ce7c7def387db53afb28e7249c
  • alt-php56-opcache_5.6.40-149_amd64.deb
    sha:65d9a64b81a2428d76eff5e4884a6d47f5818754
  • alt-php56-pdo_5.6.40-149_amd64.deb
    sha:d5bc03d87e88eef73ebc0f28a2f5a2fe404f601d
  • alt-php56-pgsql_5.6.40-149_amd64.deb
    sha:2ff1afa8dca3c17b3e34d8ae97341b56f807ae14
  • alt-php56-php-fpm_5.6.40-149_amd64.deb
    sha:a0c5862430183ae6be89b458f40f59b83da51859
  • alt-php56-process_5.6.40-149_amd64.deb
    sha:8c3c94cb8c469b27a39bf794e49ab5c8ca93fa4c
  • alt-php56-pspell_5.6.40-149_amd64.deb
    sha:0638df03bcfca54e0623f98a0aa046c934562546
  • alt-php56-recode_5.6.40-149_amd64.deb
    sha:e8ef6ba46f8ba6bc9d7a169401484bd4dd3162bf
  • alt-php56-snmp_5.6.40-149_amd64.deb
    sha:a4e7034b681e9646e553421f531ddbbfed1f0d9f
  • alt-php56-soap_5.6.40-149_amd64.deb
    sha:7e528fb5b7db146020ecea5c02b3a8457fe5821a
  • alt-php56-sybase_5.6.40-149_amd64.deb
    sha:1fc4510293b8042f91c00626ce7a40f34c941446
  • alt-php56-tidy_5.6.40-149_amd64.deb
    sha:13f50aa7cdae1f859992375657614af12378a4ce
  • alt-php56-xml_5.6.40-149_amd64.deb
    sha:f9962af829213e435e7cf212e8f7dec673b0cbea
  • alt-php56-xmlrpc_5.6.40-149_amd64.deb
    sha:4d8aeafb24afe1773180631bc0994e1aa562ad2f
Notes:
This page is generated automatically and has not been checked for errors. For clarification or corrections please contact the CloudLinux Packaging Team.