-
Notifications
You must be signed in to change notification settings - Fork 278
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9747 from wolfi-dev/fix/postgresql-15-openssl
postgresql-15: add backported openssl patch
- Loading branch information
Showing
3 changed files
with
345 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
From 5dd30bb54bfec14e5677aff3e306edec79c204ef Mon Sep 17 00:00:00 2001 | ||
From: Tom Lane <[email protected]> | ||
Date: Tue, 28 Nov 2023 12:34:03 -0500 | ||
Subject: [PATCH] Use BIO_{get,set}_app_data instead of BIO_{get,set}_data. | ||
|
||
We should have done it this way all along, but we accidentally got | ||
away with using the wrong BIO field up until OpenSSL 3.2. There, | ||
the library's BIO routines that we rely on use the "data" field | ||
for their own purposes, and our conflicting use causes assorted | ||
weird behaviors up to and including core dumps when SSL connections | ||
are attempted. Switch to using the approved field for the purpose, | ||
i.e. app_data. | ||
|
||
While at it, remove our configure probes for BIO_get_data as well | ||
as the fallback implementation. BIO_{get,set}_app_data have been | ||
there since long before any OpenSSL version that we still support, | ||
even in the back branches. | ||
|
||
Also, update src/test/ssl/t/001_ssltests.pl to allow for a minor | ||
change in an error message spelling that evidently came in with 3.2. | ||
|
||
Tristan Partin and Bo Andreson. Back-patch to all supported branches. | ||
|
||
Discussion: https://postgr.es/m/CAN55FZ1eDDYsYaL7mv+oSLUij2h_u6hvD4Qmv-7PK7jkji0uyQ@mail.gmail.com | ||
--- | ||
configure | 2 +- | ||
configure.ac | 2 +- | ||
src/backend/libpq/be-secure-openssl.c | 11 +++-------- | ||
src/include/pg_config.h.in | 3 --- | ||
src/interfaces/libpq/fe-secure-openssl.c | 11 +++-------- | ||
src/test/ssl/t/001_ssltests.pl | 4 ++-- | ||
src/tools/msvc/Solution.pm | 2 -- | ||
7 files changed, 10 insertions(+), 25 deletions(-) | ||
|
||
diff --git a/configure b/configure | ||
index d83a402ea111..d55440cd6a40 100755 | ||
--- a/configure | ||
+++ b/configure | ||
@@ -13239,7 +13239,7 @@ done | ||
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it | ||
# doesn't have these OpenSSL 1.1.0 functions. So check for individual | ||
# functions. | ||
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free | ||
+ for ac_func in OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free | ||
do : | ||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` | ||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" | ||
diff --git a/configure.ac b/configure.ac | ||
index 570daced81b1..2bc752ca1ab9 100644 | ||
--- a/configure.ac | ||
+++ b/configure.ac | ||
@@ -1347,7 +1347,7 @@ if test "$with_ssl" = openssl ; then | ||
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it | ||
# doesn't have these OpenSSL 1.1.0 functions. So check for individual | ||
# functions. | ||
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free]) | ||
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free]) | ||
# OpenSSL versions before 1.1.0 required setting callback functions, for | ||
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock() | ||
# function was removed. | ||
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c | ||
index f5c5ed210e22..aed8a75345aa 100644 | ||
--- a/src/backend/libpq/be-secure-openssl.c | ||
+++ b/src/backend/libpq/be-secure-openssl.c | ||
@@ -839,11 +839,6 @@ be_tls_write(Port *port, void *ptr, size_t len, int *waitfor) | ||
* to retry; do we need to adopt their logic for that? | ||
*/ | ||
|
||
-#ifndef HAVE_BIO_GET_DATA | ||
-#define BIO_get_data(bio) (bio->ptr) | ||
-#define BIO_set_data(bio, data) (bio->ptr = data) | ||
-#endif | ||
- | ||
static BIO_METHOD *my_bio_methods = NULL; | ||
|
||
static int | ||
@@ -853,7 +848,7 @@ my_sock_read(BIO *h, char *buf, int size) | ||
|
||
if (buf != NULL) | ||
{ | ||
- res = secure_raw_read(((Port *) BIO_get_data(h)), buf, size); | ||
+ res = secure_raw_read(((Port *) BIO_get_app_data(h)), buf, size); | ||
BIO_clear_retry_flags(h); | ||
if (res <= 0) | ||
{ | ||
@@ -873,7 +868,7 @@ my_sock_write(BIO *h, const char *buf, int size) | ||
{ | ||
int res = 0; | ||
|
||
- res = secure_raw_write(((Port *) BIO_get_data(h)), buf, size); | ||
+ res = secure_raw_write(((Port *) BIO_get_app_data(h)), buf, size); | ||
BIO_clear_retry_flags(h); | ||
if (res <= 0) | ||
{ | ||
@@ -949,7 +944,7 @@ my_SSL_set_fd(Port *port, int fd) | ||
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); | ||
goto err; | ||
} | ||
- BIO_set_data(bio, port); | ||
+ BIO_set_app_data(bio, port); | ||
|
||
BIO_set_fd(bio, fd, BIO_NOCLOSE); | ||
SSL_set_bio(port->ssl, bio, bio); | ||
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in | ||
index d09e9f9a1c3f..768e3d719c15 100644 | ||
--- a/src/include/pg_config.h.in | ||
+++ b/src/include/pg_config.h.in | ||
@@ -77,9 +77,6 @@ | ||
/* Define to 1 if you have the `backtrace_symbols' function. */ | ||
#undef HAVE_BACKTRACE_SYMBOLS | ||
|
||
-/* Define to 1 if you have the `BIO_get_data' function. */ | ||
-#undef HAVE_BIO_GET_DATA | ||
- | ||
/* Define to 1 if you have the `BIO_meth_new' function. */ | ||
#undef HAVE_BIO_METH_NEW | ||
|
||
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c | ||
index 62f813df68db..d863d279a07b 100644 | ||
--- a/src/interfaces/libpq/fe-secure-openssl.c | ||
+++ b/src/interfaces/libpq/fe-secure-openssl.c | ||
@@ -1800,11 +1800,6 @@ PQsslAttribute(PGconn *conn, const char *attribute_name) | ||
* to retry; do we need to adopt their logic for that? | ||
*/ | ||
|
||
-#ifndef HAVE_BIO_GET_DATA | ||
-#define BIO_get_data(bio) (bio->ptr) | ||
-#define BIO_set_data(bio, data) (bio->ptr = data) | ||
-#endif | ||
- | ||
/* protected by ssl_config_mutex */ | ||
static BIO_METHOD *my_bio_methods; | ||
|
||
@@ -1813,7 +1808,7 @@ my_sock_read(BIO *h, char *buf, int size) | ||
{ | ||
int res; | ||
|
||
- res = pqsecure_raw_read((PGconn *) BIO_get_data(h), buf, size); | ||
+ res = pqsecure_raw_read((PGconn *) BIO_get_app_data(h), buf, size); | ||
BIO_clear_retry_flags(h); | ||
if (res < 0) | ||
{ | ||
@@ -1843,7 +1838,7 @@ my_sock_write(BIO *h, const char *buf, int size) | ||
{ | ||
int res; | ||
|
||
- res = pqsecure_raw_write((PGconn *) BIO_get_data(h), buf, size); | ||
+ res = pqsecure_raw_write((PGconn *) BIO_get_app_data(h), buf, size); | ||
BIO_clear_retry_flags(h); | ||
if (res < 0) | ||
{ | ||
@@ -1962,7 +1957,7 @@ my_SSL_set_fd(PGconn *conn, int fd) | ||
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB); | ||
goto err; | ||
} | ||
- BIO_set_data(bio, conn); | ||
+ BIO_set_app_data(bio, conn); | ||
|
||
SSL_set_bio(conn->ssl, bio, bio); | ||
BIO_set_fd(bio, fd, BIO_NOCLOSE); | ||
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl | ||
index 707f4005af50..c570b48a1bdd 100644 | ||
--- a/src/test/ssl/t/001_ssltests.pl | ||
+++ b/src/test/ssl/t/001_ssltests.pl | ||
@@ -682,7 +682,7 @@ sub switch_server_cert | ||
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " | ||
. sslkey('client-revoked.key'), | ||
"certificate authorization fails with revoked client cert", | ||
- expected_stderr => qr/SSL error: sslv3 alert certificate revoked/, | ||
+ expected_stderr => qr|SSL error: ssl[a-z0-9/]* alert certificate revoked|, | ||
# revoked certificates should not authenticate the user | ||
log_unlike => [qr/connection authenticated:/],); | ||
|
||
@@ -743,6 +743,6 @@ sub switch_server_cert | ||
"$common_connstr user=ssltestuser sslcert=ssl/client-revoked.crt " | ||
. sslkey('client-revoked.key'), | ||
"certificate authorization fails with revoked client cert with server-side CRL directory", | ||
- expected_stderr => qr/SSL error: sslv3 alert certificate revoked/); | ||
+ expected_stderr => qr|SSL error: ssl[a-z0-9/]* alert certificate revoked|); | ||
|
||
done_testing(); | ||
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm | ||
index 790f03b05e65..a53239fa2870 100644 | ||
--- a/src/tools/msvc/Solution.pm | ||
+++ b/src/tools/msvc/Solution.pm | ||
@@ -226,7 +226,6 @@ sub GenerateFiles | ||
HAVE_ATOMICS => 1, | ||
HAVE_ATOMIC_H => undef, | ||
HAVE_BACKTRACE_SYMBOLS => undef, | ||
- HAVE_BIO_GET_DATA => undef, | ||
HAVE_BIO_METH_NEW => undef, | ||
HAVE_CLOCK_GETTIME => undef, | ||
HAVE_COMPUTED_GOTO => undef, | ||
@@ -566,7 +565,6 @@ sub GenerateFiles | ||
|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')) | ||
{ | ||
$define{HAVE_ASN1_STRING_GET0_DATA} = 1; | ||
- $define{HAVE_BIO_GET_DATA} = 1; | ||
$define{HAVE_BIO_METH_NEW} = 1; | ||
$define{HAVE_HMAC_CTX_FREE} = 1; | ||
$define{HAVE_HMAC_CTX_NEW} = 1; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
From b97226815030be274f13a114cf8ebf0063899c41 Mon Sep 17 00:00:00 2001 | ||
From: Michael Paquier <[email protected]> | ||
Date: Mon, 27 Nov 2023 09:40:50 +0900 | ||
Subject: [PATCH] Fix race condition with BIO methods initialization in libpq | ||
with threads | ||
|
||
The libpq code in charge of creating per-connection SSL objects was | ||
prone to a race condition when loading the custom BIO methods needed by | ||
my_SSL_set_fd(). As BIO methods are stored as a static variable, the | ||
initialization of a connection could fail because it could be possible | ||
to have one thread refer to my_bio_methods while it is being manipulated | ||
by a second concurrent thread. | ||
|
||
This error has been introduced by 8bb14cdd33de, that has removed | ||
ssl_config_mutex around the call of my_SSL_set_fd(), that itself sets | ||
the custom BIO methods used in libpq. Like previously, the BIO method | ||
initialization is now protected by the existing ssl_config_mutex, itself | ||
initialized earlier for WIN32. | ||
|
||
While on it, document that my_bio_methods is protected by | ||
ssl_config_mutex, as this can be easy to miss. | ||
|
||
Reported-by: Willi Mann | ||
Author: Willi Mann, Michael Paquier | ||
Discussion: https://postgr.es/m/[email protected] | ||
Backpatch-through: 12 | ||
--- | ||
src/interfaces/libpq/fe-secure-openssl.c | 73 +++++++++++++++++------- | ||
1 file changed, 51 insertions(+), 22 deletions(-) | ||
|
||
diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c | ||
index af59ff49f706..62f813df68db 100644 | ||
--- a/src/interfaces/libpq/fe-secure-openssl.c | ||
+++ b/src/interfaces/libpq/fe-secure-openssl.c | ||
@@ -1805,6 +1805,7 @@ PQsslAttribute(PGconn *conn, const char *attribute_name) | ||
#define BIO_set_data(bio, data) (bio->ptr = data) | ||
#endif | ||
|
||
+/* protected by ssl_config_mutex */ | ||
static BIO_METHOD *my_bio_methods; | ||
|
||
static int | ||
@@ -1870,6 +1871,15 @@ my_sock_write(BIO *h, const char *buf, int size) | ||
static BIO_METHOD * | ||
my_BIO_s_socket(void) | ||
{ | ||
+ BIO_METHOD *res; | ||
+ | ||
+#ifdef ENABLE_THREAD_SAFETY | ||
+ if (pthread_mutex_lock(&ssl_config_mutex)) | ||
+ return NULL; | ||
+#endif | ||
+ | ||
+ res = my_bio_methods; | ||
+ | ||
if (!my_bio_methods) | ||
{ | ||
BIO_METHOD *biom = (BIO_METHOD *) BIO_s_socket(); | ||
@@ -1878,39 +1888,58 @@ my_BIO_s_socket(void) | ||
|
||
my_bio_index = BIO_get_new_index(); | ||
if (my_bio_index == -1) | ||
- return NULL; | ||
+ goto err; | ||
my_bio_index |= (BIO_TYPE_DESCRIPTOR | BIO_TYPE_SOURCE_SINK); | ||
- my_bio_methods = BIO_meth_new(my_bio_index, "libpq socket"); | ||
- if (!my_bio_methods) | ||
- return NULL; | ||
+ res = BIO_meth_new(my_bio_index, "libpq socket"); | ||
+ if (!res) | ||
+ goto err; | ||
|
||
/* | ||
* As of this writing, these functions never fail. But check anyway, | ||
* like OpenSSL's own examples do. | ||
*/ | ||
- if (!BIO_meth_set_write(my_bio_methods, my_sock_write) || | ||
- !BIO_meth_set_read(my_bio_methods, my_sock_read) || | ||
- !BIO_meth_set_gets(my_bio_methods, BIO_meth_get_gets(biom)) || | ||
- !BIO_meth_set_puts(my_bio_methods, BIO_meth_get_puts(biom)) || | ||
- !BIO_meth_set_ctrl(my_bio_methods, BIO_meth_get_ctrl(biom)) || | ||
- !BIO_meth_set_create(my_bio_methods, BIO_meth_get_create(biom)) || | ||
- !BIO_meth_set_destroy(my_bio_methods, BIO_meth_get_destroy(biom)) || | ||
- !BIO_meth_set_callback_ctrl(my_bio_methods, BIO_meth_get_callback_ctrl(biom))) | ||
+ if (!BIO_meth_set_write(res, my_sock_write) || | ||
+ !BIO_meth_set_read(res, my_sock_read) || | ||
+ !BIO_meth_set_gets(res, BIO_meth_get_gets(biom)) || | ||
+ !BIO_meth_set_puts(res, BIO_meth_get_puts(biom)) || | ||
+ !BIO_meth_set_ctrl(res, BIO_meth_get_ctrl(biom)) || | ||
+ !BIO_meth_set_create(res, BIO_meth_get_create(biom)) || | ||
+ !BIO_meth_set_destroy(res, BIO_meth_get_destroy(biom)) || | ||
+ !BIO_meth_set_callback_ctrl(res, BIO_meth_get_callback_ctrl(biom))) | ||
{ | ||
- BIO_meth_free(my_bio_methods); | ||
- my_bio_methods = NULL; | ||
- return NULL; | ||
+ goto err; | ||
} | ||
#else | ||
- my_bio_methods = malloc(sizeof(BIO_METHOD)); | ||
- if (!my_bio_methods) | ||
- return NULL; | ||
- memcpy(my_bio_methods, biom, sizeof(BIO_METHOD)); | ||
- my_bio_methods->bread = my_sock_read; | ||
- my_bio_methods->bwrite = my_sock_write; | ||
+ res = malloc(sizeof(BIO_METHOD)); | ||
+ if (!res) | ||
+ goto err; | ||
+ memcpy(res, biom, sizeof(BIO_METHOD)); | ||
+ res->bread = my_sock_read; | ||
+ res->bwrite = my_sock_write; | ||
#endif | ||
} | ||
- return my_bio_methods; | ||
+ | ||
+ my_bio_methods = res; | ||
+ | ||
+#ifdef ENABLE_THREAD_SAFETY | ||
+ pthread_mutex_unlock(&ssl_config_mutex); | ||
+#endif | ||
+ | ||
+ return res; | ||
+ | ||
+err: | ||
+#ifdef HAVE_BIO_METH_NEW | ||
+ if (res) | ||
+ BIO_meth_free(res); | ||
+#else | ||
+ if (res) | ||
+ free(res); | ||
+#endif | ||
+ | ||
+#ifdef ENABLE_THREAD_SAFETY | ||
+ pthread_mutex_unlock(&ssl_config_mutex); | ||
+#endif | ||
+ return NULL; | ||
} | ||
|
||
/* This should exactly match OpenSSL's SSL_set_fd except for using my BIO */ |