import CS git postgresql-12.22-7.el8
This commit is contained in:
parent
6ee4778461
commit
70d1a0d58d
1862
SOURCES/postgresql-CVE-2026-6473.patch
Normal file
1862
SOURCES/postgresql-CVE-2026-6473.patch
Normal file
File diff suppressed because it is too large
Load Diff
155
SOURCES/postgresql-CVE-2026-6475.patch
Normal file
155
SOURCES/postgresql-CVE-2026-6475.patch
Normal file
@ -0,0 +1,155 @@
|
||||
From 9923bac72843cd02938868b59284cae16ae24183 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Khartskhaev <pkhartsk@redhat.com>
|
||||
Date: Thu, 4 Jun 2026 16:01:59 +0200
|
||||
Subject: [PATCH] Prevent path traversal in pg_basebackup and pg_rewind
|
||||
|
||||
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
|
||||
---
|
||||
src/bin/pg_rewind/file_ops.c | 23 +++++++++++++++++++++++
|
||||
src/include/port.h | 1 +
|
||||
src/port/path.c | 17 +++++++++++++++++
|
||||
3 files changed, 41 insertions(+)
|
||||
|
||||
diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c
|
||||
index f9e41b1..9b218a4 100644
|
||||
--- a/src/bin/pg_rewind/file_ops.c
|
||||
+++ b/src/bin/pg_rewind/file_ops.c
|
||||
@@ -43,6 +43,9 @@ open_target_file(const char *path, bool trunc)
|
||||
{
|
||||
int mode;
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target file path is unsafe for open: \"%s\"", path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -173,6 +176,9 @@ remove_target_file(const char *path, bool missing_ok)
|
||||
{
|
||||
char dstpath[MAXPGPATH];
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target file path is unsafe for removal: \"%s\"", path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -193,6 +199,9 @@ truncate_target_file(const char *path, off_t newsize)
|
||||
char dstpath[MAXPGPATH];
|
||||
int fd;
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target file path is unsafe for truncation: \"%s\"", path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -215,6 +224,10 @@ create_target_dir(const char *path)
|
||||
{
|
||||
char dstpath[MAXPGPATH];
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target directory path is unsafe for directory creation: \"%s\"",
|
||||
+ path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -229,6 +242,10 @@ remove_target_dir(const char *path)
|
||||
{
|
||||
char dstpath[MAXPGPATH];
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target directory path is unsafe for directory removal: \"%s\"",
|
||||
+ path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -243,6 +260,9 @@ create_target_symlink(const char *path, const char *link)
|
||||
{
|
||||
char dstpath[MAXPGPATH];
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target symlink path is unsafe for creation: \"%s\"", path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
@@ -257,6 +277,9 @@ remove_target_symlink(const char *path)
|
||||
{
|
||||
char dstpath[MAXPGPATH];
|
||||
|
||||
+ if (!path_is_safe_for_extraction(path))
|
||||
+ pg_fatal("target symlink path is unsafe for removal: \"%s\"", path);
|
||||
+
|
||||
if (dry_run)
|
||||
return;
|
||||
|
||||
diff --git a/src/include/port.h b/src/include/port.h
|
||||
index 32925ad..21a8f8a 100644
|
||||
--- a/src/include/port.h
|
||||
+++ b/src/include/port.h
|
||||
@@ -54,6 +54,7 @@ extern void make_native_path(char *path);
|
||||
extern void cleanup_path(char *path);
|
||||
extern bool path_contains_parent_reference(const char *path);
|
||||
extern bool path_is_relative_and_below_cwd(const char *path);
|
||||
+extern bool path_is_safe_for_extraction(const char *path);
|
||||
extern bool path_is_prefix_of_path(const char *path1, const char *path2);
|
||||
extern char *make_absolute_path(const char *path);
|
||||
extern const char *get_progname(const char *argv0);
|
||||
diff --git a/src/port/path.c b/src/port/path.c
|
||||
index 710988b..db30842 100644
|
||||
--- a/src/port/path.c
|
||||
+++ b/src/port/path.c
|
||||
@@ -428,6 +428,23 @@ path_is_relative_and_below_cwd(const char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Detect whether a path is safe for use during archive extraction.
|
||||
+ *
|
||||
+ * This applies canonicalize_path(), then it checks that the path does
|
||||
+ * not contain any parent directory references.
|
||||
+ */
|
||||
+bool
|
||||
+path_is_safe_for_extraction(const char *path)
|
||||
+{
|
||||
+ char buf[MAXPGPATH];
|
||||
+
|
||||
+ strlcpy(buf, path, sizeof(buf));
|
||||
+ canonicalize_path(buf);
|
||||
+
|
||||
+ return path_is_relative_and_below_cwd(buf);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Detect whether path1 is a prefix of path2 (including equality).
|
||||
*
|
||||
--
|
||||
2.54.0
|
||||
|
||||
222
SOURCES/postgresql-CVE-2026-6477.patch
Normal file
222
SOURCES/postgresql-CVE-2026-6477.patch
Normal file
@ -0,0 +1,222 @@
|
||||
From 7174222c87a07fbc0423f2b9bde3cea2cada311c Mon Sep 17 00:00:00 2001
|
||||
From: Petr Khartskhaev <pkhartsk@redhat.com>
|
||||
Date: Thu, 4 Jun 2026 16:01:38 +0200
|
||||
Subject: [PATCH] fix CVE-2026-6477
|
||||
|
||||
---
|
||||
doc/src/sgml/libpq.sgml | 11 ++++++++---
|
||||
src/interfaces/libpq/fe-exec.c | 18 ++++++++++++++++--
|
||||
src/interfaces/libpq/fe-lobj.c | 12 ++++++------
|
||||
src/interfaces/libpq/fe-protocol2.c | 16 +++++++++++++++-
|
||||
src/interfaces/libpq/fe-protocol3.c | 14 +++++++++++++-
|
||||
src/interfaces/libpq/libpq-int.h | 9 +++++++--
|
||||
6 files changed, 65 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
|
||||
index cda4e8d..3e87183 100644
|
||||
--- a/doc/src/sgml/libpq.sgml
|
||||
+++ b/doc/src/sgml/libpq.sgml
|
||||
@@ -5272,15 +5272,20 @@ int PQrequestCancel(PGconn *conn);
|
||||
to send simple function calls to the server.
|
||||
</para>
|
||||
|
||||
- <tip>
|
||||
+ <warning>
|
||||
<para>
|
||||
- This interface is somewhat obsolete, as one can achieve similar
|
||||
+ This interface is unsafe and should not be used. When
|
||||
+ <parameter>result_is_int</parameter> is set to <literal>0</literal>,
|
||||
+ <function>PQfn</function> may write data beyond the end of
|
||||
+ <parameter>result_buf</parameter>, regardless of whether the buffer has
|
||||
+ enough space for the requested number of bytes. Furthermore, it is
|
||||
+ obsolete, as one can achieve similar
|
||||
performance and greater functionality by setting up a prepared
|
||||
statement to define the function call. Then, executing the statement
|
||||
with binary transmission of parameters and results substitutes for a
|
||||
fast-path function call.
|
||||
</para>
|
||||
- </tip>
|
||||
+ </warning>
|
||||
|
||||
<para>
|
||||
The function <function>PQfn</function><indexterm><primary>PQfn</primary></indexterm>
|
||||
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
|
||||
index ff101c4..5dea7e7 100644
|
||||
--- a/src/interfaces/libpq/fe-exec.c
|
||||
+++ b/src/interfaces/libpq/fe-exec.c
|
||||
@@ -2661,6 +2661,20 @@ PQfn(PGconn *conn,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args,
|
||||
int nargs)
|
||||
+{
|
||||
+ return PQnfn(conn, fnid, result_buf, -1, result_len,
|
||||
+ result_is_int, args, nargs);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * PQnfn
|
||||
+ * Private version of PQfn() with verification that returned data fits in
|
||||
+ * result_buf when result_is_int == 0. Setting buf_size to -1 disables
|
||||
+ * this verification.
|
||||
+ */
|
||||
+PGresult *
|
||||
+PQnfn(PGconn *conn, int fnid, int *result_buf, int buf_size, int *result_len,
|
||||
+ int result_is_int, const PQArgBlock *args, int nargs)
|
||||
{
|
||||
*result_len = 0;
|
||||
|
||||
@@ -2680,12 +2694,12 @@ PQfn(PGconn *conn,
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
|
||||
return pqFunctionCall3(conn, fnid,
|
||||
- result_buf, result_len,
|
||||
+ result_buf, buf_size, result_len,
|
||||
result_is_int,
|
||||
args, nargs);
|
||||
else
|
||||
return pqFunctionCall2(conn, fnid,
|
||||
- result_buf, result_len,
|
||||
+ result_buf, buf_size, result_len,
|
||||
result_is_int,
|
||||
args, nargs);
|
||||
}
|
||||
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
|
||||
index 6866d64..b019b9e 100644
|
||||
--- a/src/interfaces/libpq/fe-lobj.c
|
||||
+++ b/src/interfaces/libpq/fe-lobj.c
|
||||
@@ -288,8 +288,8 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
|
||||
argv[1].len = 4;
|
||||
argv[1].u.integer = (int) len;
|
||||
|
||||
- res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
|
||||
- (void *) buf, &result_len, 0, argv, 2);
|
||||
+ res = PQnfn(conn, conn->lobjfuncs->fn_lo_read,
|
||||
+ (void *) buf, len, &result_len, 0, argv, 2);
|
||||
if (PQresultStatus(res) == PGRES_COMMAND_OK)
|
||||
{
|
||||
PQclear(res);
|
||||
@@ -439,8 +439,8 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
|
||||
argv[2].len = 4;
|
||||
argv[2].u.integer = whence;
|
||||
|
||||
- res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek64,
|
||||
- (void *) &retval, &result_len, 0, argv, 3);
|
||||
+ res = PQnfn(conn, conn->lobjfuncs->fn_lo_lseek64,
|
||||
+ (void *) &retval, sizeof(retval), &result_len, 0, argv, 3);
|
||||
if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
|
||||
{
|
||||
PQclear(res);
|
||||
@@ -605,8 +605,8 @@ lo_tell64(PGconn *conn, int fd)
|
||||
argv[0].len = 4;
|
||||
argv[0].u.integer = fd;
|
||||
|
||||
- res = PQfn(conn, conn->lobjfuncs->fn_lo_tell64,
|
||||
- (void *) &retval, &result_len, 0, argv, 1);
|
||||
+ res = PQnfn(conn, conn->lobjfuncs->fn_lo_tell64,
|
||||
+ (void *) &retval, sizeof(retval), &result_len, 0, argv, 1);
|
||||
if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8)
|
||||
{
|
||||
PQclear(res);
|
||||
diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
|
||||
index 0e36974..b4f0c10 100644
|
||||
--- a/src/interfaces/libpq/fe-protocol2.c
|
||||
+++ b/src/interfaces/libpq/fe-protocol2.c
|
||||
@@ -1434,7 +1434,7 @@ pqEndcopy2(PGconn *conn)
|
||||
*/
|
||||
PGresult *
|
||||
pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
- int *result_buf, int *actual_result_len,
|
||||
+ int *result_buf, int buf_size, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs)
|
||||
{
|
||||
@@ -1516,6 +1516,20 @@ pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
}
|
||||
else
|
||||
{
|
||||
+ /*
|
||||
+ * If the server returned too much data for the
|
||||
+ * buffer, something fishy is going on. Abandon ship.
|
||||
+ */
|
||||
+ if (buf_size != -1 && *actual_result_len > buf_size)
|
||||
+ {
|
||||
+ appendPQExpBufferStr(&conn->errorMessage,
|
||||
+ libpq_gettext("server returned too much data\n"));
|
||||
+ conn->asyncStatus = PGASYNC_READY;
|
||||
+ pqDropConnection(conn, true);
|
||||
+ conn->status = CONNECTION_BAD;
|
||||
+ return pqPrepareAsyncResult(conn);
|
||||
+ }
|
||||
+
|
||||
if (pqGetnchar((char *) result_buf,
|
||||
*actual_result_len,
|
||||
conn))
|
||||
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
|
||||
index c9f88ba..2931453 100644
|
||||
--- a/src/interfaces/libpq/fe-protocol3.c
|
||||
+++ b/src/interfaces/libpq/fe-protocol3.c
|
||||
@@ -1893,7 +1893,7 @@ pqEndcopy3(PGconn *conn)
|
||||
*/
|
||||
PGresult *
|
||||
pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
- int *result_buf, int *actual_result_len,
|
||||
+ int *result_buf, int buf_size, int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs)
|
||||
{
|
||||
@@ -2024,6 +2024,18 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
}
|
||||
else
|
||||
{
|
||||
+ /*
|
||||
+ * If the server returned too much data for the
|
||||
+ * buffer, something fishy is going on. Abandon ship.
|
||||
+ */
|
||||
+ if (buf_size != -1 && *actual_result_len > buf_size)
|
||||
+ {
|
||||
+ appendPQExpBufferStr(&conn->errorMessage,
|
||||
+ libpq_gettext("server returned too much data\n"));
|
||||
+ handleSyncLoss(conn, id, *actual_result_len);
|
||||
+ return pqPrepareAsyncResult(conn);
|
||||
+ }
|
||||
+
|
||||
if (pqGetnchar((char *) result_buf,
|
||||
*actual_result_len,
|
||||
conn))
|
||||
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
|
||||
index 7ecbd55..1a073ff 100644
|
||||
--- a/src/interfaces/libpq/libpq-int.h
|
||||
+++ b/src/interfaces/libpq/libpq-int.h
|
||||
@@ -606,6 +606,9 @@ extern void pqSaveMessageField(PGresult *res, char code,
|
||||
extern void pqSaveParameterStatus(PGconn *conn, const char *name,
|
||||
const char *value);
|
||||
extern int pqRowProcessor(PGconn *conn, const char **errmsgp);
|
||||
+extern PGresult *PQnfn(PGconn *conn, int fnid, int *result_buf, int buf_size,
|
||||
+ int *result_len, int result_is_int,
|
||||
+ const PQArgBlock *args, int nargs);
|
||||
|
||||
/* === in fe-protocol2.c === */
|
||||
|
||||
@@ -619,7 +622,8 @@ extern int pqGetline2(PGconn *conn, char *s, int maxlen);
|
||||
extern int pqGetlineAsync2(PGconn *conn, char *buffer, int bufsize);
|
||||
extern int pqEndcopy2(PGconn *conn);
|
||||
extern PGresult *pqFunctionCall2(PGconn *conn, Oid fnid,
|
||||
- int *result_buf, int *actual_result_len,
|
||||
+ int *result_buf, int buf_size,
|
||||
+ int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
|
||||
@@ -636,7 +640,8 @@ extern int pqGetline3(PGconn *conn, char *s, int maxlen);
|
||||
extern int pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize);
|
||||
extern int pqEndcopy3(PGconn *conn);
|
||||
extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid,
|
||||
- int *result_buf, int *actual_result_len,
|
||||
+ int *result_buf, int buf_size,
|
||||
+ int *actual_result_len,
|
||||
int result_is_int,
|
||||
const PQArgBlock *args, int nargs);
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
250
SOURCES/postgresql-CVE-2026-6478.patch
Normal file
250
SOURCES/postgresql-CVE-2026-6478.patch
Normal file
@ -0,0 +1,250 @@
|
||||
Created by combining upstream commit 4608619a1cf578f16e799510eaa0a21c0f1f08e3
|
||||
that fixes the CVE
|
||||
with upstream commit b282280e9b69cae988c0c69cce3eda4d4bd38fff
|
||||
that provides the function the fix uses, `timingsafe_bcmp`
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index 350d426..7537c19 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -16305,6 +16305,16 @@ fi
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_DECL_RTLD_NOW $ac_have_decl
|
||||
_ACEOF
|
||||
+ac_fn_c_check_decl "$LINENO" "timingsafe_bcmp" "ac_cv_have_decl_timingsafe_bcmp" "$ac_includes_default"
|
||||
+if test "x$ac_cv_have_decl_timingsafe_bcmp" = xyes; then :
|
||||
+ ac_have_decl=1
|
||||
+else
|
||||
+ ac_have_decl=0
|
||||
+fi
|
||||
+
|
||||
+cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_DECL_TIMINGSAFE_BCMP $ac_have_decl
|
||||
+_ACEOF
|
||||
|
||||
|
||||
ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "$ac_includes_default
|
||||
@@ -16617,6 +16627,19 @@ esac
|
||||
|
||||
fi
|
||||
|
||||
+ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp"
|
||||
+if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then :
|
||||
+ $as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h
|
||||
+
|
||||
+else
|
||||
+ case " $LIBOBJS " in
|
||||
+ *" timingsafe_bcmp.$ac_objext "* ) ;;
|
||||
+ *) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext"
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+fi
|
||||
+
|
||||
|
||||
|
||||
case $host_os in
|
||||
diff --git a/configure.in b/configure.in
|
||||
index ffce35e..a29366d 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -1780,7 +1780,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
|
||||
]) # fi
|
||||
|
||||
AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
|
||||
-AC_CHECK_DECLS([strlcat, strlcpy, strnlen])
|
||||
+AC_CHECK_DECLS([strlcat, strlcpy, strnlen, timingsafe_bcmp])
|
||||
# This is probably only present on macOS, but may as well check always
|
||||
AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
|
||||
|
||||
@@ -1841,6 +1841,7 @@ AC_REPLACE_FUNCS(m4_normalize([
|
||||
strlcpy
|
||||
strnlen
|
||||
strtof
|
||||
+ timingsafe_bcmp
|
||||
]))
|
||||
|
||||
case $host_os in
|
||||
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
|
||||
index 6b60abe..def1fce 100644
|
||||
--- a/src/backend/libpq/auth-scram.c
|
||||
+++ b/src/backend/libpq/auth-scram.c
|
||||
@@ -535,7 +535,7 @@ scram_verify_plain_password(const char *username, const char *password,
|
||||
* Compare the verifier's Server Key with the one computed from the
|
||||
* user-supplied password.
|
||||
*/
|
||||
- return memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
|
||||
+ return timingsafe_bcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1050,9 +1050,9 @@ verify_final_nonce(scram_state *state)
|
||||
|
||||
if (final_nonce_len != client_nonce_len + server_nonce_len)
|
||||
return false;
|
||||
- if (memcmp(state->client_final_nonce, state->client_nonce, client_nonce_len) != 0)
|
||||
+ if (timingsafe_bcmp(state->client_final_nonce, state->client_nonce, client_nonce_len) != 0)
|
||||
return false;
|
||||
- if (memcmp(state->client_final_nonce + client_nonce_len, state->server_nonce, server_nonce_len) != 0)
|
||||
+ if (timingsafe_bcmp(state->client_final_nonce + client_nonce_len, state->server_nonce, server_nonce_len) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -1093,7 +1093,7 @@ verify_client_proof(scram_state *state)
|
||||
/* Hash it one more time, and compare with StoredKey */
|
||||
scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey);
|
||||
|
||||
- if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
|
||||
+ if (timingsafe_bcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
|
||||
index 98b4225..c61615f 100644
|
||||
--- a/src/backend/libpq/auth.c
|
||||
+++ b/src/backend/libpq/auth.c
|
||||
@@ -3345,7 +3345,7 @@ PerformRadiusTransaction(const char *server, const char *secret, const char *por
|
||||
}
|
||||
pfree(cryptvector);
|
||||
|
||||
- if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
|
||||
+ if (timingsafe_bcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
|
||||
{
|
||||
ereport(LOG,
|
||||
(errmsg("RADIUS response from %s has incorrect MD5 signature",
|
||||
diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c
|
||||
index 6e273dc..95cd78d 100644
|
||||
--- a/src/backend/libpq/crypt.c
|
||||
+++ b/src/backend/libpq/crypt.c
|
||||
@@ -199,7 +199,8 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
- if (strcmp(client_pass, crypt_pwd) == 0)
|
||||
+ if (strlen(client_pass) == strlen(crypt_pwd) &&
|
||||
+ timingsafe_bcmp(client_pass, crypt_pwd, strlen(crypt_pwd)) == 0)
|
||||
retval = STATUS_OK;
|
||||
else
|
||||
{
|
||||
@@ -264,7 +265,8 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
|
||||
*/
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
- if (strcmp(crypt_client_pass, shadow_pass) == 0)
|
||||
+ if (strlen(crypt_client_pass) == strlen(shadow_pass) &&
|
||||
+ timingsafe_bcmp(crypt_client_pass, shadow_pass, strlen(shadow_pass)) == 0)
|
||||
return STATUS_OK;
|
||||
else
|
||||
{
|
||||
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
|
||||
index c876033..d2f3477 100644
|
||||
--- a/src/include/pg_config.h.in
|
||||
+++ b/src/include/pg_config.h.in
|
||||
@@ -189,6 +189,10 @@
|
||||
don't. */
|
||||
#undef HAVE_DECL_STRTOULL
|
||||
|
||||
+/* Define to 1 if you have the declaration of `timingsafe_bcmp', and to 0 if
|
||||
+ you don't. */
|
||||
+#undef HAVE_DECL_TIMINGSAFE_BCMP
|
||||
+
|
||||
/* Define to 1 if you have the `dlopen' function. */
|
||||
#undef HAVE_DLOPEN
|
||||
|
||||
@@ -661,6 +665,9 @@
|
||||
`HAVE_STRUCT_TM_TM_ZONE' instead. */
|
||||
#undef HAVE_TM_ZONE
|
||||
|
||||
+/* Define to 1 if you have the `timingsafe_bcmp' function. */
|
||||
+#undef HAVE_TIMINGSAFE_BCMP
|
||||
+
|
||||
/* Define to 1 if your compiler understands `typeof' or something similar. */
|
||||
#undef HAVE_TYPEOF
|
||||
|
||||
diff --git a/src/include/port.h b/src/include/port.h
|
||||
index 2229ec7..32925ad 100644
|
||||
--- a/src/include/port.h
|
||||
+++ b/src/include/port.h
|
||||
@@ -497,6 +497,10 @@ extern int pqGethostbyname(const char *name,
|
||||
struct hostent **result,
|
||||
int *herrno);
|
||||
|
||||
+#if !HAVE_DECL_TIMINGSAFE_BCMP
|
||||
+extern int timingsafe_bcmp(const void *b1, const void *b2, size_t len);
|
||||
+#endif
|
||||
+
|
||||
extern void pg_qsort(void *base, size_t nel, size_t elsize,
|
||||
int (*cmp) (const void *, const void *));
|
||||
extern int pg_qsort_strcmp(const void *a, const void *b);
|
||||
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
|
||||
index 6b55bff..f87e6f7 100644
|
||||
--- a/src/interfaces/libpq/fe-auth-scram.c
|
||||
+++ b/src/interfaces/libpq/fe-auth-scram.c
|
||||
@@ -549,7 +549,7 @@ read_server_first_message(fe_scram_state *state, char *input)
|
||||
|
||||
/* Verify immediately that the server used our part of the nonce */
|
||||
if (strlen(nonce) < strlen(state->client_nonce) ||
|
||||
- memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
|
||||
+ timingsafe_bcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
|
||||
{
|
||||
printfPQExpBuffer(&conn->errorMessage,
|
||||
libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
|
||||
@@ -748,7 +748,8 @@ verify_server_signature(fe_scram_state *state)
|
||||
strlen(state->client_final_message_without_proof));
|
||||
scram_HMAC_final(expected_ServerSignature, &ctx);
|
||||
|
||||
- if (memcmp(expected_ServerSignature, state->ServerSignature, SCRAM_KEY_LEN) != 0)
|
||||
+ if (timingsafe_bcmp(expected_ServerSignature, state->ServerSignature,
|
||||
+ SCRAM_KEY_LEN) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
diff --git a/src/port/timingsafe_bcmp.c b/src/port/timingsafe_bcmp.c
|
||||
new file mode 100644
|
||||
index 0000000..fbad8a7
|
||||
--- /dev/null
|
||||
+++ b/src/port/timingsafe_bcmp.c
|
||||
@@ -0,0 +1,43 @@
|
||||
+/*
|
||||
+ * src/port/timingsafe_bcmp.c
|
||||
+ *
|
||||
+ * $OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "c.h"
|
||||
+
|
||||
+#ifdef USE_SSL
|
||||
+#include <openssl/crypto.h>
|
||||
+#endif
|
||||
+
|
||||
+int
|
||||
+timingsafe_bcmp(const void *b1, const void *b2, size_t n)
|
||||
+{
|
||||
+#ifdef USE_SSL
|
||||
+ return CRYPTO_memcmp(b1, b2, n);
|
||||
+#else
|
||||
+ const unsigned char *p1 = b1,
|
||||
+ *p2 = b2;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ for (; n > 0; n--)
|
||||
+ ret |= *p1++ ^ *p2++;
|
||||
+ return (ret != 0);
|
||||
+#endif
|
||||
+}
|
||||
202
SOURCES/postgresql-CVE-2026-6637.patch
Normal file
202
SOURCES/postgresql-CVE-2026-6637.patch
Normal file
@ -0,0 +1,202 @@
|
||||
From 44abf5b7e2b9892edce3ec78bf26e1b5ebf796f9 Mon Sep 17 00:00:00 2001
|
||||
From: Petr Khartskhaev <pkhartsk@redhat.com>
|
||||
Date: Thu, 4 Jun 2026 16:01:19 +0200
|
||||
Subject: [PATCH] refint: Fix SQL injection and buffer overruns.
|
||||
|
||||
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
|
||||
---
|
||||
contrib/spi/refint.c | 84 ++++++++++++++++++++------------------------
|
||||
1 file changed, 38 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c
|
||||
index adf0490..266f65e 100644
|
||||
--- a/contrib/spi/refint.c
|
||||
+++ b/contrib/spi/refint.c
|
||||
@@ -165,21 +165,24 @@ check_primary_key(PG_FUNCTION_ARGS)
|
||||
if (plan->nplans <= 0)
|
||||
{
|
||||
SPIPlanPtr pplan;
|
||||
- char sql[8192];
|
||||
+ StringInfoData sql;
|
||||
+
|
||||
+ initStringInfo(&sql);
|
||||
|
||||
/*
|
||||
* Construct query: SELECT 1 FROM _referenced_relation_ WHERE Pkey1 =
|
||||
* $1 [AND Pkey2 = $2 [...]]
|
||||
*/
|
||||
- snprintf(sql, sizeof(sql), "select 1 from %s where ", relname);
|
||||
- for (i = 0; i < nkeys; i++)
|
||||
+ appendStringInfo(&sql, "select 1 from %s where ", relname);
|
||||
+ for (i = 1; i <= nkeys; i++)
|
||||
{
|
||||
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s = $%d %s",
|
||||
- args[i + nkeys + 1], i + 1, (i < nkeys - 1) ? "and " : "");
|
||||
+ appendStringInfo(&sql, "%s = $%d ", args[i + nkeys], i);
|
||||
+ if (i < nkeys)
|
||||
+ appendStringInfoString(&sql, "and ");
|
||||
}
|
||||
|
||||
/* Prepare plan for query */
|
||||
- pplan = SPI_prepare(sql, nkeys, argtypes);
|
||||
+ pplan = SPI_prepare(sql.data, nkeys, argtypes);
|
||||
if (pplan == NULL)
|
||||
/* internal error */
|
||||
elog(ERROR, "check_primary_key: SPI_prepare returned %s", SPI_result_code_string(SPI_result));
|
||||
@@ -194,6 +197,8 @@ check_primary_key(PG_FUNCTION_ARGS)
|
||||
plan->splan = (SPIPlanPtr *) malloc(sizeof(SPIPlanPtr));
|
||||
*(plan->splan) = pplan;
|
||||
plan->nplans = 1;
|
||||
+
|
||||
+ pfree(sql.data);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -414,13 +419,16 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
||||
if (plan->nplans <= 0)
|
||||
{
|
||||
SPIPlanPtr pplan;
|
||||
- char sql[8192];
|
||||
char **args2 = args;
|
||||
|
||||
plan->splan = (SPIPlanPtr *) malloc(nrefs * sizeof(SPIPlanPtr));
|
||||
|
||||
for (r = 0; r < nrefs; r++)
|
||||
{
|
||||
+ StringInfoData sql;
|
||||
+
|
||||
+ initStringInfo(&sql);
|
||||
+
|
||||
relname = args2[0];
|
||||
|
||||
/*---------
|
||||
@@ -434,8 +442,7 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
||||
*---------
|
||||
*/
|
||||
if (action == 'r')
|
||||
-
|
||||
- snprintf(sql, sizeof(sql), "select 1 from %s where ", relname);
|
||||
+ appendStringInfo(&sql, "select 1 from %s where ", relname);
|
||||
|
||||
/*---------
|
||||
* For 'C'ascade action we construct DELETE query
|
||||
@@ -462,43 +469,24 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
||||
char *nv;
|
||||
int k;
|
||||
|
||||
- snprintf(sql, sizeof(sql), "update %s set ", relname);
|
||||
+ appendStringInfo(&sql, "update %s set ", relname);
|
||||
for (k = 1; k <= nkeys; k++)
|
||||
{
|
||||
- int is_char_type = 0;
|
||||
- char *type;
|
||||
-
|
||||
fn = SPI_fnumber(tupdesc, args_temp[k - 1]);
|
||||
Assert(fn > 0); /* already checked above */
|
||||
nv = SPI_getvalue(newtuple, tupdesc, fn);
|
||||
- type = SPI_gettype(tupdesc, fn);
|
||||
-
|
||||
- if (strcmp(type, "text") == 0 ||
|
||||
- strcmp(type, "varchar") == 0 ||
|
||||
- strcmp(type, "char") == 0 ||
|
||||
- strcmp(type, "bpchar") == 0 ||
|
||||
- strcmp(type, "date") == 0 ||
|
||||
- strcmp(type, "timestamp") == 0)
|
||||
- is_char_type = 1;
|
||||
-#ifdef DEBUG_QUERY
|
||||
- elog(DEBUG4, "check_foreign_key Debug value %s type %s %d",
|
||||
- nv, type, is_char_type);
|
||||
-#endif
|
||||
|
||||
- /*
|
||||
- * is_char_type =1 i set ' ' for define a new value
|
||||
- */
|
||||
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql),
|
||||
- " %s = %s%s%s %s ",
|
||||
- args2[k], (is_char_type > 0) ? "'" : "",
|
||||
- nv, (is_char_type > 0) ? "'" : "", (k < nkeys) ? ", " : "");
|
||||
+ appendStringInfo(&sql, " %s = %s ",
|
||||
+ args2[k], quote_literal_cstr(nv));
|
||||
+ if (k < nkeys)
|
||||
+ appendStringInfoString(&sql, ", ");
|
||||
}
|
||||
- strcat(sql, " where ");
|
||||
+ appendStringInfoString(&sql, " where ");
|
||||
|
||||
}
|
||||
else
|
||||
/* DELETE */
|
||||
- snprintf(sql, sizeof(sql), "delete from %s where ", relname);
|
||||
+ appendStringInfo(&sql, "delete from %s where ", relname);
|
||||
|
||||
}
|
||||
|
||||
@@ -510,25 +498,26 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
else if (action == 's')
|
||||
{
|
||||
- snprintf(sql, sizeof(sql), "update %s set ", relname);
|
||||
+ appendStringInfo(&sql, "update %s set ", relname);
|
||||
for (i = 1; i <= nkeys; i++)
|
||||
{
|
||||
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql),
|
||||
- "%s = null%s",
|
||||
- args2[i], (i < nkeys) ? ", " : "");
|
||||
+ appendStringInfo(&sql, "%s = null", args2[i]);
|
||||
+ if (i < nkeys)
|
||||
+ appendStringInfoString(&sql, ", ");
|
||||
}
|
||||
- strcat(sql, " where ");
|
||||
+ appendStringInfoString(&sql, " where ");
|
||||
}
|
||||
|
||||
/* Construct WHERE qual */
|
||||
for (i = 1; i <= nkeys; i++)
|
||||
{
|
||||
- snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s = $%d %s",
|
||||
- args2[i], i, (i < nkeys) ? "and " : "");
|
||||
+ appendStringInfo(&sql, "%s = $%d ", args2[i], i);
|
||||
+ if (i < nkeys)
|
||||
+ appendStringInfoString(&sql, "and ");
|
||||
}
|
||||
|
||||
/* Prepare plan for query */
|
||||
- pplan = SPI_prepare(sql, nkeys, argtypes);
|
||||
+ pplan = SPI_prepare(sql.data, nkeys, argtypes);
|
||||
if (pplan == NULL)
|
||||
/* internal error */
|
||||
elog(ERROR, "check_foreign_key: SPI_prepare returned %s", SPI_result_code_string(SPI_result));
|
||||
@@ -544,11 +533,14 @@ check_foreign_key(PG_FUNCTION_ARGS)
|
||||
plan->splan[r] = pplan;
|
||||
|
||||
args2 += nkeys + 1; /* to the next relation */
|
||||
+
|
||||
+#ifdef DEBUG_QUERY
|
||||
+ elog(DEBUG4, "check_foreign_key Debug Query is : %s ", sql.data);
|
||||
+#endif
|
||||
+
|
||||
+ pfree(sql.data);
|
||||
}
|
||||
plan->nplans = nrefs;
|
||||
-#ifdef DEBUG_QUERY
|
||||
- elog(DEBUG4, "check_foreign_key Debug Query is : %s ", sql);
|
||||
-#endif
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@ -1,25 +1,84 @@
|
||||
From 9d18b30ac7a17d70ee789b710865bd20b206023d Mon Sep 17 00:00:00 2001
|
||||
From: Filip Janus <fjanus@redhat.com>
|
||||
Date: Tue, 18 Mar 2025 10:11:09 +0100
|
||||
Subject: [PATCH] Fix failing test regardless the CVE-2025-1094 fix
|
||||
From dee1e86d0e6d20c6326073db1736ae2088aac191 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Lane <tgl@sss.pgh.pa.us>
|
||||
Date: Mon, 20 Jan 2025 15:47:53 -0500
|
||||
Subject: [PATCH] Avoid using timezone Asia/Manila in regression tests.
|
||||
|
||||
The freshly-released 2025a version of tzdata has a refined estimate
|
||||
for the longitude of Manila, changing their value for LMT in
|
||||
pre-standardized-timezone days. This changes the output of one of
|
||||
our test cases. Since we need to be able to run with system tzdata
|
||||
files that may or may not contain this update, we'd better stop
|
||||
making that specific test.
|
||||
|
||||
I switched it to use Asia/Singapore, which has a roughly similar UTC
|
||||
offset. That LMT value hasn't changed in tzdb since 2003, so we can
|
||||
hope that it's well established.
|
||||
|
||||
I also noticed that this set of make_timestamptz tests only exercises
|
||||
zones east of Greenwich, which seems rather sad, and was not the
|
||||
original intent AFAICS. (We've already changed these tests once
|
||||
to stabilize their results across tzdata updates, cf 66b737cd9;
|
||||
it looks like I failed to consider the UTC-offset-sign aspect then.)
|
||||
To improve that, add a test with Pacific/Honolulu. That LMT offset
|
||||
is also quite old in tzdb, so we'll cross our fingers that it doesn't
|
||||
get improved.
|
||||
|
||||
Reported-by: Christoph Berg <cb@df7cb.de>
|
||||
Discussion: https://postgr.es/m/Z46inkznCxesvDEb@msg.df7cb.de
|
||||
Backpatch-through: 13
|
||||
---
|
||||
src/test/regress/expected/timestamptz.out | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
src/include/datatype/timestamp.h | 2 +-
|
||||
src/test/regress/expected/timestamptz.out | 10 ++++++++--
|
||||
src/test/regress/sql/timestamptz.sql | 3 ++-
|
||||
3 files changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h
|
||||
index 6be6d35d1e2c2..92b1cca9901be 100644
|
||||
--- a/src/include/datatype/timestamp.h
|
||||
+++ b/src/include/datatype/timestamp.h
|
||||
@@ -96,7 +96,7 @@ typedef struct
|
||||
/*
|
||||
* We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
|
||||
* Currently, the record holders for wackiest offsets in actual use are zones
|
||||
- * Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
|
||||
+ * Asia/Manila, at -15:56:08 until 1844, and America/Metlakatla, at +15:13:42
|
||||
* until 1867. If we were to reject such values we would fail to dump and
|
||||
* restore old timestamptz values with these zone settings.
|
||||
*/
|
||||
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
|
||||
index 55efd183868..5964b65bc6b 100644
|
||||
index 0ce33862019b2..77abfab1f6663 100644
|
||||
--- a/src/test/regress/expected/timestamptz.out
|
||||
+++ b/src/test/regress/expected/timestamptz.out
|
||||
@@ -2060,7 +2060,7 @@ SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UT
|
||||
SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC';
|
||||
@@ -2072,10 +2072,16 @@ SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UT
|
||||
Tue Dec 09 23:00:00 2014
|
||||
(1 row)
|
||||
|
||||
-SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC';
|
||||
+SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Asia/Singapore') AT TIME ZONE 'UTC';
|
||||
timezone
|
||||
--------------------------
|
||||
- Wed Dec 09 15:56:00 1846
|
||||
+ Wed Dec 09 15:56:08 1846
|
||||
+ Fri Dec 09 17:04:35 1881
|
||||
+(1 row)
|
||||
+
|
||||
+SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Pacific/Honolulu') AT TIME ZONE 'UTC';
|
||||
+ timezone
|
||||
+--------------------------
|
||||
+ Sat Dec 10 10:31:26 1881
|
||||
(1 row)
|
||||
|
||||
SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Europe/Paris') AT TIME ZONE 'UTC';
|
||||
--
|
||||
2.39.5 (Apple Git-154)
|
||||
|
||||
diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql
|
||||
index f0a8d3e5aa6dc..ac0bc14854956 100644
|
||||
--- a/src/test/regress/sql/timestamptz.sql
|
||||
+++ b/src/test/regress/sql/timestamptz.sql
|
||||
@@ -331,7 +331,8 @@ SELECT make_timestamptz(1973, 07, 15, 08, 15, 55.33, '+2') = '1973-07-15 08:15:5
|
||||
-- full timezone names
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') = timestamptz '2014-12-10 00:00:00 Europe/Prague';
|
||||
SELECT make_timestamptz(2014, 12, 10, 0, 0, 0, 'Europe/Prague') AT TIME ZONE 'UTC';
|
||||
-SELECT make_timestamptz(1846, 12, 10, 0, 0, 0, 'Asia/Manila') AT TIME ZONE 'UTC';
|
||||
+SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Asia/Singapore') AT TIME ZONE 'UTC';
|
||||
+SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Pacific/Honolulu') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(1881, 12, 10, 0, 0, 0, 'Europe/Paris') AT TIME ZONE 'UTC';
|
||||
SELECT make_timestamptz(1910, 12, 24, 0, 0, 0, 'Nehwon/Lankhmar');
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ Summary: PostgreSQL client programs
|
||||
Name: postgresql
|
||||
%global majorversion 12
|
||||
Version: %{majorversion}.22
|
||||
Release: 6%{?dist}
|
||||
Release: 7%{?dist}
|
||||
|
||||
# The PostgreSQL license is very similar to other MIT licenses, but the OSI
|
||||
# recognizes it as an independent license, so we do as well.
|
||||
@ -112,10 +112,17 @@ Patch11: backport-cve-2025-1094.patch
|
||||
Patch12: timezone-test-fix.patch
|
||||
Patch13: CVE-2025-8715.patch
|
||||
Patch14: CVE-2026-2004--CVE-2026-2005--CVE-2026-2006.patch
|
||||
Patch15: postgresql-CVE-2026-6478.patch
|
||||
Patch16: postgresql-CVE-2026-6637.patch
|
||||
Patch17: postgresql-CVE-2026-6477.patch
|
||||
Patch18: postgresql-CVE-2026-6475.patch
|
||||
Patch19: postgresql-CVE-2026-6473.patch
|
||||
|
||||
BuildRequires: gcc
|
||||
BuildRequires: perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk
|
||||
BuildRequires: perl(ExtUtils::Embed), perl-devel
|
||||
BuildRequires: perl(Opcode)
|
||||
BuildRequires: perl(FindBin)
|
||||
%if 0%{?fedora} || 0%{?rhel} > 7
|
||||
BuildRequires: perl-generators
|
||||
%endif
|
||||
@ -123,6 +130,7 @@ BuildRequires: readline-devel zlib-devel
|
||||
BuildRequires: systemd systemd-devel util-linux
|
||||
BuildRequires: multilib-rpm-config
|
||||
BuildRequires: libpq-devel
|
||||
BuildRequires: docbook-style-xsl
|
||||
|
||||
|
||||
# postgresql-setup build requires
|
||||
@ -378,6 +386,11 @@ benchmarks.
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
%patch17 -p1
|
||||
%patch18 -p1
|
||||
%patch19 -p1
|
||||
|
||||
# We used to run autoconf here, but there's no longer any real need to,
|
||||
# since Postgres ships with a reasonably modern configure script.
|
||||
@ -1233,6 +1246,11 @@ make -C postgresql-setup-%{setup_version} check
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Jun 4 2026 Petr Khartskhaev <pkhartsk@redhat.com> - 12.22-7
|
||||
- Backport fix for CVE-2026-6478 from PostgreSQL 14.23
|
||||
- Backport fixes for CVE-2026-6637, CVE-2026-6477, CVE-2026-6475, CVE-2026-6473
|
||||
- Resolves: RHEL-179790
|
||||
|
||||
* Fri Feb 27 2026 Filip Janus <fjanus@redhat.com> - 12.22-6
|
||||
- Fix CVE-2026-2004 CVE-2026-2005 CVE-2026-2006
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user