Cherry-pick recent CVE fixes#1736
Open
reshke wants to merge 17 commits into
Open
Conversation
The number of NFA states, number of NFA arcs, and number of colors are all bounded to reasonably small values. However, there are places where we try to allocate arrays sized by products of those quantities, and those calculations could overflow, enabling buffer-overrun attacks. In practice there's no problem on 64-bit machines, but there are some live scenarios on 32-bit machines. A related problem is that citerdissect() and creviterdissect() allocate arrays based on the length of the input string, which potentially could overflow. To fix, invent MALLOC_ARRAY and REALLOC_ARRAY macros that rely on palloc_array_extended and repalloc_array_extended with the NO_OOM option, similarly to the existing MALLOC and REALLOC macros. (Like those, they'll throw an error not return a NULL result for oversize requests. This doesn't really fit into the regex code's view of error handling, but it'll do for now. We can consider whether to change that behavior in a non-security follow-up patch.) I installed similar defenses in the colormap construction code. It's not entirely clear whether integer overflow is possible there, but analyzing the behavior in detail seems not worth the trouble, as the risky spots are not in hot code paths. I left a bunch of calls as-is after verifying that they can't overflow given reasonable limits on nstates and narcs. Those limits were enforced already via REG_MAX_COMPILE_SPACE, but add commentary to document the interactions. In passing, also fix a related edge case, which is that the special color numbers used in LACON carcs could overflow the "color" data type, if ncolors is close to MAX_COLOR. In v14 and v15, the regex engine calls malloc() directly instead of using palloc(), so MALLOC_ARRAY and REALLOC_ARRAY do likewise. Reported-by: Xint Code Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Backpatch-through: 14 Security: CVE-2026-6473
Some UTF8 characters decompose to more than a dozen codepoints. It is possible for an input string that fits into well under 1GB to produce more than 4G decomposed codepoints, causing unicode_normalize()'s decomp_size variable to wrap around to a small positive value. This results in a small output buffer allocation and subsequent buffer overrun. To fix, test after each addition to see if we've overrun MaxAllocSize, and break out of the loop early if so. In frontend code we want to just return NULL for this failure (treating it like OOM). In the backend, we can rely on the following palloc() call to throw error. I also tightened things up in the calling functions in varlena.c, using size_t rather than int and allocating the input workspace with palloc_array(). These changes are probably unnecessary given the knowledge that the original input and the normalized output_chars array must fit into 1GB, but it's a lot easier to believe the code is safe with these changes. Reported-by: Xint Code Reported-by: Bruce Dang <bruce@calif.io> Author: Tom Lane <tgl@sss.pgh.pa.us> Co-authored-by: Heikki Linnakangas <hlinnaka@iki.fi> Backpatch-through: 14 Security: CVE-2026-6473
multirange_recv and BlockRefTableReaderNextRelation were incautious about multiplying a possibly-large integer by a factor more than 1 and then using it as an allocation size. This is harmless on 64-bit systems where we'd compute a size exceeding MaxAllocSize and then fail, but on 32-bit systems we could overflow size_t leading to an undersized allocation and buffer overrun. Fix these places by using palloc_array() instead of a handwritten multiplication. (In HEAD, some of them were fixed already, but none of that work got back-patched at the time.) In addition, BlockRefTableReaderNextRelation passes the same value to BlockRefTableRead's "int length" parameter. If built for 64-bit frontend code, palloc_array() allows a larger array size than it otherwise would, potentially allowing that parameter to overflow. Add an explicit check to forestall that and keep the behavior the same cross-platform. Reported-by: Xint Code Author: Tom Lane <tgl@sss.pgh.pa.us> Backpatch-through: 14 Security: CVE-2026-6473
These two routines will be used in a test of an upcoming fix. This commit affects the v14~v17 range. v18 and newer versions already include them, thanks to 85ec945b7880. Security: CVE-2026-6479 Backpatch-through: 14
The handling of SSL and GSS negotiation messages in ProcessStartupPacket() could cause a recursion of the backend, ultimately crashing the server as the negotiation attempts were not tracked across multiple calls processing startup packets. A malicious client could therefore alternate rejected SSL and GSS requests indefinitely, each adding a stack frame, until the backend crashed with a stack overflow, taking down a server. This commit addresses this issue by modifying ProcessStartupPacket() so as processed negotiation attempts are tracked, preventing infinite recursive attempts. A TAP test is added to check this problem, where multiple SSL and GSS negotiated attempts are stacked. Reported-by: Calif.io in collaboration with Claude and Anthropic Research Author: Michael Paquier <michael@paquier.xyz> Reviewed-by: Daniel Gustafsson <daniel@yesql.se> Security: CVE-2026-6479 Backpatch-through: 14
Define MaxAllocSize in src/include/common/fe_memutils.h rather than having several copies of it in different src/common/*.c files. This also provides an opportunity to document it better. Back-patch of commit 11b7de4a7, needed now because assorted security fixes are adding additional references to MaxAllocSize in frontend code. Backpatch-through: 14-17 Security: CVE-2026-6473
contrib/intarray's query_int type uses an int16 field to hold the offset from a binary operator node to its left operand. However, it allows the number of nodes to be as much as will fit in MaxAllocSize, so there is a risk of overflowing int16 depending on the precise shape of the tree. Simple right-associative cases like "a | b | c | ..." work fine, so we should not solve this by restricting the overall number of nodes. Instead add a direct test of whether each individual offset is too large. contrib/ltree's ltxtquery type uses essentially the same logic and has the same 16-bit restriction. (The core backend's tsquery.c has a variant of this logic too, but in that case the target field is 32 bits, so it is okay so long as varlena datums are restricted to 1GB.) In v16 and up, these types support soft error reporting, so we have to complicate the recursive findoprnd function's API a bit to allow the complaint to be reported softly. v14/v15 don't need that. Undocumented and overcomplicated code like this makes my head hurt, so add some comments and simplify while at it. Reported-by: Xint Code Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Michael Paquier <michael@paquier.xyz> Backpatch-through: 14 Security: CVE-2026-6473
This commit applies timingsafe_bcmp() to authentication paths that handle attributes or data previously compared with memcpy() or strcmp(), which are sensitive to timing attacks. The following data is concerned by this change, some being in the backend and some in the frontend: - For a SCRAM or MD5 password, the computed key or the MD5 hash compared with a password during a plain authentication. - For a SCRAM exchange, the stored key, the client's final nonce and the server nonce. - RADIUS (up to v18), the encrypted password. - For MD5 authentication, the MD5(MD5()) hash. Reported-by: Joe Conway <mail@joeconway.com> Security: CVE-2026-6478 Author: Michael Paquier <michael@paquier.xyz> Reviewed-by: John Naylor <johncnaylorls@gmail.com> Backpatch-through: 14
timeofday() assumed that the output of pg_strftime() could not contain % signs, other than the one it explicitly asks for with %%. However, we don't have that guarantee with respect to the time zone name (%Z). A crafted time zone setting could abuse the subsequent snprintf() call, resulting in crashes or disclosure of server memory. To fix, split the pg_strftime() call into two and then treat the outputs as literal strings, not a snprintf format string. The extra pg_strftime() call doesn't really cost anything, since the bulk of the conversion work was done by pg_localtime(). Also, adjust buffer widths so that we're not risking string truncation during the snprintf() step, as that would create a hazard of producing mis-encoded output. This also fixes a latent portability issue: the format string expects an int, but tp.tv_usec is long int on many platforms. Reported-by: Xint Code Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: John Naylor <johncnaylorls@gmail.com> Backpatch-through: 14 Security: CVE-2026-6474
Although pg_strftime() has defined error conditions, no callers bother to check for errors. This is problematic because the output string is very likely not null-terminated if an error occurs, so that blindly using it is unsafe. Rather than trusting that we can find and fix all the callers, let's alter the function's API spec slightly: make it guarantee a null-terminated result so long as maxsize > 0. Furthermore, if we do get an error, let's make that null-terminated result be an empty string. We could instead truncate at the buffer length, but that risks producing mis-encoded output if the tz_name string contains multibyte characters. It doesn't seem reasonable for src/timezone/ to make use of our encoding-aware truncation logic. Also, the only really likely source of a failure is a user-supplied timezone name that is intentionally trying to overrun our buffers. I don't feel a need to be particularly friendly about that case. Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: John Naylor <johncnaylorls@gmail.com> Backpatch-through: 14 Security: CVE-2026-6474
This omission allowed roles to create multirange types in any schema, potentially leading to privilege escalations. Note that when a multirange type name is not specified in CREATE TYPE, it is automatically placed in the range type's schema, which is checked at the beginning of DefineRange(). Reported-by: Jelte Fennema-Nio <postgres@jeltef.nl> Author: Jelte Fennema-Nio <postgres@jeltef.nl> Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Tomas Vondra <tomas@vondra.me> Security: CVE-2026-6472 Backpatch-through: 14
A few functions in this file were incautious about multiplying a possibly large integer by a factor more than 1 and then using it as an allocation size. This is harmless on 64-bit systems where we'd compute a size exceeding MaxAllocSize and then fail, but on 32-bit systems we could overflow size_t, leading to an undersized allocation and buffer overrun. To fix, use palloc_array() or mul_size() instead of handwritten multiplication. Reported-by: Sven Klemm <sven@tigerdata.com> Reported-by: Xint Code Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Tatsuo Ishii <ishii@postgresql.org> Security: CVE-2026-6473 Backpatch-through: 14
pg_rewind and pg_basebackup could be fed paths from rogue endpoints that could overwrite the contents of the client when received, achieving path traversal. There were two areas in the tree that were sensitive to this problem: - pg_basebackup, through the astreamer code, where no validation was performed before building an output path when streaming tar data. This is an issue in v15 and newer versions. - pg_rewind file operations for paths received through libpq, for all the stable branches supported. In order to address this problem, this commit adds a helper function in path.c, that reuses path_is_relative_and_below_cwd() after applying canonicalize_path(). This can be used to validate the paths received from a connection point. A path is considered invalid if any of the two following conditions is satisfied: - The path is absolute. - The path includes a direct parent-directory reference. Reported-by: XlabAI Team of Tencent Xuanwu Lab Reported-by: Valery Gubanov <valerygubanov95@gmail.com> Author: Michael Paquier <michael@paquier.xyz> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Backpatch-through: 14 Security: CVE-2026-6475
pg_locale_icu.c was full of places where a very long input string could cause integer overflow while calculating a buffer size, leading to buffer overruns. It also was cavalier about using char-type local arrays as buffers holding arrays of UChar. The alignment of a char[] variable isn't guaranteed, so that this risked failure on alignment-picky platforms. The lack of complaints suggests that such platforms are very rare nowadays; but it's likely that we are paying a performance price on rather more platforms. Declare those arrays as UChar[] instead, keeping their physical size the same. pg_locale_libc.c's strncoll_libc_win32_utf8() also had the disease of assuming it could double or quadruple the input string length without concern for overflow. Reported-by: Xint Code Reported-by: Pavel Kohout <pavel.kohout@aisle.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Backpatch-through: 14 Security: CVE-2026-6473
If you accumulate many arrays full of NULLs, you could overflow 'nitems', before reaching the MaxAllocSize limit on the allocations. Add an explicit check that the number of items doesn't grow too large. With more than MaxArraySize items, getting the final result with makeArrayResultArr() would fail anyway, so better to error out early. Reported-by: Xint Code Author: Heikki Linnakangas <heikki.linnakangas@iki.fi> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Backpatch-through: 14 Security: CVE-2026-6473
When result_is_int is set to 0, PQfn() cannot validate that the result fits in result_buf, so it will write data beyond the end of the buffer when the server returns more data than requested. Since this function is insecurable and obsolete, add a warning to the top of the pertinent documentation advising against its use. The only in-tree caller of PQfn() is the frontend large object interface. To fix that, add a buf_size parameter to pqFunctionCall3() that is used to protect against overruns, and use it in a private version of PQfn() that also accepts a buf_size parameter. Reported-by: Yu Kunpeng <yu443940816@live.com> Reported-by: Martin Heistermann <martin.heistermann@unibe.ch> Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Noah Misch <noah@leadboat.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Etsuro Fujita <etsuro.fujita@gmail.com> Security: CVE-2026-6477 Backpatch-through: 14
Maliciously crafted key value updates could achieve SQL injection within check_foreign_key(). To fix, ensure new key values are properly quoted and escaped in the internally generated SQL statements. While at it, avoid potential buffer overruns by replacing the stack buffers for internally generated SQL statements with StringInfo. Reported-by: Nikolay Samokhvalov <nik@postgres.ai> Author: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Noah Misch <noah@leadboat.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Fujii Masao <masao.fujii@gmail.com> Security: CVE-2026-6637 Backpatch-through: 14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://git.postgresql.org/cgit/postgresql.git/log/?h=REL_14_STABLE
Following commits excluded due to non-trivial conflict, will take care of them separately
b545c378767
2d267ffc449
37842f3dc6c
61a9b4b6e4f
b282280e9b6