From 4711e45a237e841349106e1948dcecb339dde9ce Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 4 Nov 2026 20:55:38 +0000 Subject: [PATCH 1/2] ext/openssl: session reuse sharing callbacks with a persistent stream. Fix #25172 Reusing a session onto a pfsockopen() stream shared the parent's request heap callback structures, which were then freed with the wrong allocator at shutdown. The reuse is now refused with a warning. --- ext/openssl/xp_ssl.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index f96c2cdb220d..dcde68176b8b 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2797,6 +2797,14 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, php_stream_warn(stream, SslNotSupported, "Supplied SSL session stream is not set up"); } else if (sslsock->is_client && parent_sslsock->ssl_handle == NULL) { php_stream_warn(stream, SslNotSupported, "Supplied SSL session stream is not initialized"); + } else if (php_stream_is_persistent(stream) && + (parent_sslsock->session_callbacks + || parent_sslsock->psk_callbacks +#if defined(HAVE_TLS13) + || parent_sslsock->early_data_callbacks +#endif + )) { + php_stream_warn(stream, PersistentNotSupported, "Supplied SSL session stream with callbacks is not supported for persistent streams"); } else { SSL_CTX_up_ref(parent_sslsock->ctx); sslsock->ctx = parent_sslsock->ctx; From 482621a7726a52ed642f1be47e11be548185c302 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 4 Nov 2026 21:25:50 +0000 Subject: [PATCH 2/2] add test --- ext/openssl/tests/gh25172.phpt | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 ext/openssl/tests/gh25172.phpt diff --git a/ext/openssl/tests/gh25172.phpt b/ext/openssl/tests/gh25172.phpt new file mode 100644 index 000000000000..8cd231e1b988 --- /dev/null +++ b/ext/openssl/tests/gh25172.phpt @@ -0,0 +1,49 @@ +--TEST-- +GH-25172: TLS session reuse must not share callbacks with a persistent stream +--EXTENSIONS-- +openssl +--CREDITS-- +cxxz16 +--FILE-- + $options]); + $parent = stream_socket_client("tcp://$addr", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $ctx); + stream_set_blocking($parent, false); + var_dump(stream_socket_enable_crypto($parent, true, $method)); + + $child = pfsockopen($host, (int) $port); + stream_set_blocking($child, false); + var_dump(stream_socket_enable_crypto($child, true, $method, $parent)); +} + +reuse_on_persistent( + ['psk_client_cb' => fn() => new Openssl\Psk(str_repeat('k', 32), 'id')], + STREAM_CRYPTO_METHOD_TLS_CLIENT, +); +reuse_on_persistent( + ['session_new_cb' => function () {}], + STREAM_CRYPTO_METHOD_TLS_CLIENT, +); +reuse_on_persistent( + ['early_data_cb' => function () {}], + STREAM_CRYPTO_METHOD_TLS_SERVER, +); +?> +--EXPECTF-- +int(0) + +Warning: stream_socket_enable_crypto(): Supplied SSL session stream with callbacks is not supported for persistent streams in %s on line %d +int(0) +int(0) + +Warning: stream_socket_enable_crypto(): Supplied SSL session stream with callbacks is not supported for persistent streams in %s on line %d +int(0) +int(0) + +Warning: stream_socket_enable_crypto(): Supplied SSL session stream with callbacks is not supported for persistent streams in %s on line %d +int(0)