Compare commits

..

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

13 changed files with 103 additions and 2690 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/postgresql-13.23.tar.bz2
SOURCES/postgresql-13.11.tar.bz2

View File

@ -1 +1 @@
25e217f0c7bbc3150b4632eabdf77eb539a99719 SOURCES/postgresql-13.23.tar.bz2
501acb24ba8539c08ba12b08adecd7559bf87e1b SOURCES/postgresql-13.11.tar.bz2

View File

@ -7,11 +7,11 @@ directory whose path happens to include "postgres" or "pgsql" already.
However, datadir and sysconfdir are already set up in the specfile's
configure call, so we do not have to append anything to them.
diff -Naur postgresql-9.0.1.orig/src/Makefile.global.in postgresql-9.0.1/src/Makefile.global.in
--- postgresql-9.0.1.orig/src/Makefile.global.in 2010-10-01 10:25:44.000000000 -0400
+++ postgresql-9.0.1/src/Makefile.global.in 2010-10-11 11:52:05.224975308 -0400
@@ -55,8 +55,7 @@
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 9a6265b3a0..c9371a07c4 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -82,8 +82,7 @@ vpathsearch = `for f in $(addsuffix /$(1),$(subst :, ,. $(VPATH))); do test -r $
# Installation directories
#
# These are set by the equivalent --xxxdir configure options. We
@ -21,7 +21,7 @@ diff -Naur postgresql-9.0.1.orig/src/Makefile.global.in postgresql-9.0.1/src/Mak
#
# In a PGXS build, we cannot use the values inserted into Makefile.global
# by configure, since the installation tree may have been relocated.
@@ -74,45 +73,23 @@
@@ -101,45 +100,23 @@ datarootdir := @datarootdir@
bindir := @bindir@
datadir := @datadir@

View File

@ -13,10 +13,10 @@ to be updated. (Of course, a user who dislikes this behavior can still
override it via postgresql.conf.)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 9481f2d..75532c7 100644
index 4dde819652..8c2f601333 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3196,7 +3196,7 @@ static struct config_string ConfigureNamesString[] =
@@ -4159,7 +4159,7 @@ static struct config_string ConfigureNamesString[] =
},
&Unix_socket_directories,
#ifdef HAVE_UNIX_SOCKETS
@ -26,10 +26,10 @@ index 9481f2d..75532c7 100644
"",
#endif
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index feeff9e..3e3d784 100644
index 4ff0c6c700..6ccd96b1f2 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1234,7 +1234,7 @@ setup_config(void)
@@ -1091,7 +1091,7 @@ setup_config(void)
#ifdef HAVE_UNIX_SOCKETS
snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'",
@ -39,7 +39,7 @@ index feeff9e..3e3d784 100644
snprintf(repltok, sizeof(repltok), "#unix_socket_directories = ''");
#endif
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index e278fa0..9ee15d4 100644
index 8f3ec6bde1..066daf3f08 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -201,7 +201,7 @@

View File

@ -1,10 +1,13 @@
- The libpq package is supposed to be used for all the PostgreSQL modules
commit 75040c3388d9a7dd5ad2bee53cbcc8bf3d35cd17
Author: Honza Horak <hhorak@redhat.com>
Date: Fri Oct 30 20:16:50 2020 +0100
- available in RHEL 8, and ABI versioning will guarantee us that modular RPMs will
- depend on appropriate libpq ABI version (picked at build-time).
The libpq package is supposed to be used for all the PostgreSQL modules
available in RHEL 8, and ABI versioning will guarantee us that modular RPMs will
depend on appropriate libpq ABI version (picked at build-time).
diff --git a/config/Makefile b/config/Makefile
index 67e7998f55..86612a42c3 100644
index 67e7998..86612a4 100644
--- a/config/Makefile
+++ b/config/Makefile
@@ -8,6 +8,7 @@ include $(top_builddir)/src/Makefile.global
@ -76,21 +79,21 @@ index 373d73caef..d5bd5468cd 100644
ifneq (,$(exports_file))
LINK.shared += -Wl,--version-script=$(exports_file)
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index ccec59919b..4c2be8b7d5 100644
index bbc1f90..fc3ef8a 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -171,11 +171,11 @@
@@ -171,11 +171,11 @@ PQsslAttributeNames 168
PQsslAttribute 169
PQsetErrorContextVisibility 170
PQresultVerboseErrorMessage 171
-PQencryptPasswordConn 172
+PQencryptPasswordConn 172 10
-PQresultMemorySize 173
+PQencryptPasswordConn 172 10
+PQresultMemorySize 173 12
+PQresultMemorySize 173 12
PQhostaddr 174
PQgssEncInUse 175
PQgetgssctx 176
-PQsetSSLKeyPassHook_OpenSSL 177
+PQsetSSLKeyPassHook_OpenSSL 177 13
+PQsetSSLKeyPassHook_OpenSSL 177 13
PQgetSSLKeyPassHook_OpenSSL 178
PQdefaultSSLKeyPassHook_OpenSSL 179

View File

@ -0,0 +1 @@
4992ff647203566b670d4e54dc5317499a26856c93576d0ea951bdf6bee50bfb postgresql-13.11.tar.bz2

View File

@ -1 +0,0 @@
6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6 postgresql-13.23.tar.bz2

File diff suppressed because it is too large Load Diff

View File

@ -1,155 +0,0 @@
From 498829dca45ad207a23954fe2e5a30ed2ef4b363 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Mon, 11 May 2026 05:13:51 -0700
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 a807086..faaa5ce 100644
--- a/src/bin/pg_rewind/file_ops.c
+++ b/src/bin/pg_rewind/file_ops.c
@@ -48,6 +48,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;
@@ -188,6 +191,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;
@@ -208,6 +214,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;
@@ -230,6 +239,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;
@@ -244,6 +257,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;
@@ -258,6 +275,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;
@@ -272,6 +292,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 db53dec..a257d8d 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -55,6 +55,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 d37a484..117f919 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -505,6 +505,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.39.5 (Apple Git-154)

View File

@ -1,219 +0,0 @@
From 2b450648240c6c56f367e74bbf0f785b91f93396 Mon Sep 17 00:00:00 2001
From: Petr Khartskhaev <pkhartsk@redhat.com>
Date: Wed, 3 Jun 2026 16:34:32 +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 +-
13 files changed, 17098 insertions(+), 15 deletions(-)
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 1a84241..e1f688c 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -5086,15 +5086,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 id="libpq-PQfn">PQfn</function><indexterm><primary>PQfn</primary></indexterm>
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index b30b565..076a9d0 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -2665,6 +2665,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;
@@ -2684,12 +2698,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 a94ce06..01e67a3 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 9360c54..0c2b629 100644
--- a/src/interfaces/libpq/fe-protocol2.c
+++ b/src/interfaces/libpq/fe-protocol2.c
@@ -1428,7 +1428,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)
{
@@ -1510,6 +1510,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 3da1ace..a092010 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1903,7 +1903,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)
{
@@ -2034,6 +2034,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 814884a..1b0cf91 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -622,6 +622,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 === */
@@ -635,7 +638,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);
@@ -652,7 +656,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);

View File

@ -1,250 +0,0 @@
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 91df389..4b85063 100755
--- a/configure
+++ b/configure
@@ -16305,6 +16305,16 @@ fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_STRNLEN $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
# We can't use AC_REPLACE_FUNCS to replace these functions, because it
@@ -16639,6 +16649,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
+
if test "$PORTNAME" = "win32" -o "$PORTNAME" = "cygwin"; then
diff --git a/configure.in b/configure.in
index 318851d..5461fc6 100644
--- a/configure.in
+++ b/configure.in
@@ -1793,7 +1793,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])
# We can't use AC_REPLACE_FUNCS to replace these functions, because it
# won't handle deployment target restrictions on macOS
@@ -1843,6 +1843,7 @@ AC_REPLACE_FUNCS(m4_normalize([
strlcpy
strnlen
strtof
+ timingsafe_bcmp
]))
if test "$PORTNAME" = "win32" -o "$PORTNAME" = "cygwin"; then
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 5214d32..75c97ca 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -537,7 +537,7 @@ scram_verify_plain_password(const char *username, const char *password,
* Compare the secret'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;
}
@@ -1074,9 +1074,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;
@@ -1117,7 +1117,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 8b63217..e56eab1 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -3375,7 +3375,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 17b91ac..7f3aea5 100644
--- a/src/backend/libpq/crypt.c
+++ b/src/backend/libpq/crypt.c
@@ -196,7 +196,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
{
@@ -261,7 +262,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 b351a0b..d86ad1d 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -175,6 +175,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
@@ -634,6 +638,9 @@
/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
+/* 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 0e86dfb..d3ca64e 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -514,6 +514,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 3e705f8..065244c 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -612,7 +612,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"));
@@ -814,7 +814,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..288865f
--- /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
+}

View File

@ -1,203 +0,0 @@
From 2b026df29c1e1caafb259a2021528a28ec484018 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Mon, 11 May 2026 05:13:52 -0700
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 6fbfef2..cbef463 100644
--- a/contrib/spi/refint.c
+++ b/contrib/spi/refint.c
@@ -166,21 +166,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));
@@ -196,6 +199,8 @@ check_primary_key(PG_FUNCTION_ARGS)
sizeof(SPIPlanPtr));
*(plan->splan) = pplan;
plan->nplans = 1;
+
+ pfree(sql.data);
}
/*
@@ -416,7 +421,6 @@ check_foreign_key(PG_FUNCTION_ARGS)
if (plan->nplans <= 0)
{
SPIPlanPtr pplan;
- char sql[8192];
char **args2 = args;
plan->splan = (SPIPlanPtr *) MemoryContextAlloc(TopMemoryContext,
@@ -424,6 +428,10 @@ check_foreign_key(PG_FUNCTION_ARGS)
for (r = 0; r < nrefs; r++)
{
+ StringInfoData sql;
+
+ initStringInfo(&sql);
+
relname = args2[0];
/*---------
@@ -437,8 +445,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
@@ -465,43 +472,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);
}
@@ -513,25 +501,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));
@@ -547,11 +536,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.39.5 (Apple Git-154)

View File

@ -3,8 +3,8 @@
Summary: PostgreSQL client library
Name: libpq
Version: %{majorversion}.23
Release: 2%{?dist}
Version: %{majorversion}.11
Release: 1%{?dist}
License: PostgreSQL
Url: http://www.postgresql.org/
@ -16,15 +16,9 @@ Source1: https://ftp.postgresql.org/pub/source/v%{version}/postgresql-%{version}
# Comments for these patches are in the patch files.
Patch1: libpq-10.3-rpm-pgsql.patch
Patch2: libpq-10.3-var-run-socket.patch
Patch3: libpq-13.1-symbol-versioning.patch
Patch4: postgresql-CVE-2026-6478.patch
Patch5: postgresql-CVE-2026-6637.patch
Patch6: postgresql-CVE-2026-6477.patch
Patch7: postgresql-CVE-2026-6475.patch
Patch8: postgresql-CVE-2026-6473.patch
Patch3: libpq-12.1-symbol-versioning.patch
BuildRequires: gcc
BuildRequires: perl-interpreter
BuildRequires: glibc-devel bison flex gawk
BuildRequires: zlib-devel
BuildRequires: openssl-devel
@ -32,6 +26,7 @@ BuildRequires: krb5-devel
BuildRequires: openldap-devel
BuildRequires: gettext
BuildRequires: multilib-rpm-config
BuildRequires: make
Obsoletes: postgresql-libs < %obsoletes_version
Provides: postgresql-libs = %version-%release
@ -62,7 +57,7 @@ package or any clients that need to connect to a PostgreSQL server.
%prep
( cd "$(dirname "%SOURCE1")" ; sha256sum -c "%SOURCE1" )
%autosetup -n postgresql-%{version} -p1
%autosetup -n postgresql-%version -p1
# remove .gitignore files to ensure none get into the RPMs (bug #642210)
find . -type f -name .gitignore | xargs rm
@ -123,7 +118,7 @@ find_lang_bins %name-devel.lst pg_config
%files -f %name.lst
%license COPYRIGHT
%_libdir/libpq.so.*
%_libdir/libpq.so.5*
%dir %_datadir/pgsql
%doc %_datadir/pgsql/pg_service.conf.sample
@ -136,71 +131,95 @@ find_lang_bins %name-devel.lst pg_config
%changelog
* Tue Jun 09 2026 Filip Janus <fjanus@redhat.com> - 13.23-2
- Backport fixes for CVE-2026-6478, CVE-2026-6637, CVE-2026-6477,
CVE-2026-6475, CVE-2026-6473 from PostgreSQL 14.23
- Resolves: RHEL-179806
* Mon May 29 2023 Dominik Rehák <drehak@redhat.com> - 13.11-1
- Update to 13.11
Resolves: #2171370
* Mon Dec 01 2025 Filip Janus <fjanus@redhat.com> - 13.23-1
- Rebase to upstream release 13.23
- Resolves: RHEL-131269 (CVE-2025-12818)
* Tue Nov 16 2021 Marek Kulik <mkulik@redhat.com> - 13.5-1
- Update to 13.5
* Tue Feb 18 2025 Ales Nezbeda <anezbeda@redhat.com> - 13.20-1
- Update to 13.20
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 13.2-4
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Wed Jun 21 2023 Masahiro Matsuya <mmatsuya@redhat.com> - 13.11-1
- Rebase to 13.11
Resolves: #2171369
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 13.2-3
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Mon Nov 29 2021 Marek Kulik <mkulik@redhat.com> - 13.5-1
- Rebase to 13.5
Resolves: #2023294
* Mon May 31 2021 Honza Horak <hhorak@redhat.com> - 13.3-1
- Rebase to 13.3
Resolves: #1966146
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 13.2-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Feb 16 2021 Honza Horak <hhorak@redhat.com> - 13.2-1
- Rebase to 13.2
Related: #1855776
- Update to 13.2
* Tue Nov 17 2020 Patrik Novotný <panovotn@redhat.com> - 13.1-1
* Mon Feb 08 2021 Patrik Novotný <panovotn@redhat.com> - 13.1-3
- Fix symbol versioning
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 13.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Mon Nov 16 2020 Patrik Novotný <panovotn@redhat.com> - 13.1-1
- Rebase to upstream release 13.1
Resolves: BZ#1855776
(BZ#1856242 particuarly)
* Mon Aug 17 2020 Patrik Novotný <panovotn@redhat.com> - 12.4-1
* Mon Nov 02 2020 Patrik Novotný <panovotn@redhat.com> - 13.0-2
- Rebuild for symbol versioning fix
* Wed Oct 14 2020 Patrik Novotný <panovotn@redhat.com> - 13.0-1
- Rebase to upstream release 13.0
* Tue Aug 18 2020 Patrik Novotný <panovotn@redhat.com> - 12.4-1
- Rebase to upstream release 12.4
* Tue Jun 16 2020 Patrik Novotný <panovotn@redhat.com> - 12.3-1
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 12.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon May 18 2020 Patrik Novotný <panovotn@redhat.com> - 12.3-1
- Rebase to upstream release 12.3
* Tue Nov 19 2019 Patrik Novotný <panovotn@redhat.com> - 12.1-3
- Rebuild with rebased symbol versioning patch
* Mon Feb 17 2020 Patrik Novotný <panovotn@redhat.com> - 12.2-1
- Rebase to upstream release 12.2
* Fri Nov 15 2019 Patrik Novotný <panovotn@redhat.com> - 12.1-2
- Rebuild with rebased symbol versioning patch
* Tue Nov 12 2019 Patrik Novotný <panovotn@redhat.com> - 12.1-1
* Tue Feb 04 2020 Patrik Novotný <panovotn@redhat.com> - 12.1-1
- Rebase to upstream release 12.1
* Fri Nov 08 2019 Honza Horak <hhorak@redhat.com> - 12.0-2
- Bump release for a new build with gating.yaml added
Related: #1749461
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 11.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Thu Oct 03 2019 Patrik Novotný <panovotn@redhat.com> - 12.0-1
- Initial release for upstream version 12.0
* Mon Nov 25 2019 Patrik Novotný <panovotn@redhat.com> - 11.6-1
- Rebase to upstream version 11.6
* Wed Aug 08 2018 Pavel Raiskup <praiskup@redhat.com> - 10.5-1
- update to 10.5 per release notes:
https://www.postgresql.org/docs/10/static/release-10-5.html
* Wed Aug 07 2019 Petr Kubat <pkubat@redhat.com> - 11.5-1
- New upstream version 11.5
* Fri Jul 13 2018 Pavel Raiskup <praiskup@redhat.com> - 10.4-2
- ABI/symbol versioning
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 11.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Jul 12 2018 Pavel Raiskup <praiskup@redhat.com> - 10.4-1
- rebase to the latest upstream release
* Tue Jul 09 2019 Petr Kubat <pkubat@redhat.com> - 11.4-1
- New upstream version 11.4
* Fri Apr 13 2018 Pavel Raiskup <praiskup@redhat.com> - 10.3-1
- initial release, packaging inspired by postgresql.spec
- provide postgresql-devel to avoid fixing all the client packages
* Fri May 10 2019 Pavel Raiskup <praiskup@redhat.com> - 11.3-2
- obsolete anything < %%majorversion+1
* Thu May 09 2019 Patrik Novotný <panovotn@redhat.com> - 11.3-1
- New upstream version 11.3
* Mon Feb 18 2019 Pavel Raiskup <praiskup@redhat.com> - 11.2-2
- fix dnf system-upgrade from f29 to f29+, rhbz#1677849
* Thu Feb 14 2019 Pavel Raiskup <praiskup@redhat.com> - 11.2-1
- latest upstream release, per release notes:
https://www.postgresql.org/docs/11/static/release-11-1.html
https://www.postgresql.org/docs/11/static/release-11-2.html
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 11.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Oct 16 2018 Pavel Raiskup <praiskup@redhat.com> - 11.0-1
- latest upstream release, per release notes:
https://www.postgresql.org/docs/11/static/release-11-0.html
* Tue Sep 04 2018 Pavel Raiskup <praiskup@redhat.com> - 10.5-4
- fix provides/obsoletes to final state
* Thu Aug 30 2018 Pavel Raiskup <praiskup@redhat.com> - 10.5-1
- libpq packaging for Fedora