Skip to content

Commit a58b518

Browse files
[AUTO-CHERRYPICK] qt5-qtbase: Add patch to resolve CVE-2024-39936. - branch main (#10129)
Co-authored-by: Sumynwa <sumsharma@microsoft.com>
1 parent 063e609 commit a58b518

3 files changed

Lines changed: 251 additions & 1 deletion

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
2+
index d1b5dfda2e2..ee04a1856c6 100644
3+
--- a/src/network/access/qhttp2protocolhandler.cpp
4+
+++ b/src/network/access/qhttp2protocolhandler.cpp
5+
@@ -375,12 +375,12 @@ bool QHttp2ProtocolHandler::sendRequest()
6+
}
7+
}
8+
9+
- if (!prefaceSent && !sendClientPreface())
10+
- return false;
11+
-
12+
if (!requests.size())
13+
return true;
14+
15+
+ if (!prefaceSent && !sendClientPreface())
16+
+ return false;
17+
+
18+
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
19+
// Check what was promised/pushed, maybe we do not have to send a request
20+
// and have a response already?
21+
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
22+
index bd2f32e3528..6f3bd807a09 100644
23+
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
24+
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
25+
@@ -255,6 +255,10 @@ void QHttpNetworkConnectionChannel::abort()
26+
bool QHttpNetworkConnectionChannel::sendRequest()
27+
{
28+
Q_ASSERT(!protocolHandler.isNull());
29+
+ if (waitingForPotentialAbort) {
30+
+ needInvokeSendRequest = true;
31+
+ return false; // this return value is unused
32+
+ }
33+
return protocolHandler->sendRequest();
34+
}
35+
36+
@@ -267,21 +271,28 @@ bool QHttpNetworkConnectionChannel::sendRequest()
37+
void QHttpNetworkConnectionChannel::sendRequestDelayed()
38+
{
39+
QMetaObject::invokeMethod(this, [this] {
40+
- Q_ASSERT(!protocolHandler.isNull());
41+
if (reply)
42+
- protocolHandler->sendRequest();
43+
+ sendRequest();
44+
}, Qt::ConnectionType::QueuedConnection);
45+
}
46+
47+
void QHttpNetworkConnectionChannel::_q_receiveReply()
48+
{
49+
Q_ASSERT(!protocolHandler.isNull());
50+
+ if (waitingForPotentialAbort) {
51+
+ needInvokeReceiveReply = true;
52+
+ return;
53+
+ }
54+
protocolHandler->_q_receiveReply();
55+
}
56+
57+
void QHttpNetworkConnectionChannel::_q_readyRead()
58+
{
59+
Q_ASSERT(!protocolHandler.isNull());
60+
+ if (waitingForPotentialAbort) {
61+
+ needInvokeReadyRead = true;
62+
+ return;
63+
+ }
64+
protocolHandler->_q_readyRead();
65+
}
66+
67+
@@ -1289,7 +1300,18 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
68+
// Similar to HTTP/1.1 counterpart below:
69+
const auto &pairs = spdyRequestsToSend.values(); // (request, reply)
70+
const auto &pair = pairs.first();
71+
+ waitingForPotentialAbort = true;
72+
emit pair.second->encrypted();
73+
+
74+
+ // We don't send or handle any received data until any effects from
75+
+ // emitting encrypted() have been processed. This is necessary
76+
+ // because the user may have called abort(). We may also abort the
77+
+ // whole connection if the request has been aborted and there is
78+
+ // no more requests to send.
79+
+ QMetaObject::invokeMethod(this,
80+
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
81+
+ Qt::QueuedConnection);
82+
+
83+
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
84+
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
85+
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
86+
@@ -1307,6 +1329,26 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
87+
}
88+
}
89+
90+
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
91+
+{
92+
+ Q_ASSERT(connection->connectionType() > QHttpNetworkConnection::ConnectionTypeHTTP);
93+
+
94+
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
95+
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
96+
+ // effects from emitting encrypted() have been processed.
97+
+ // This function is called after encrypted() was emitted, so check for changes.
98+
+
99+
+ if (!reply && spdyRequestsToSend.isEmpty())
100+
+ abort();
101+
+ waitingForPotentialAbort = false;
102+
+ if (needInvokeReadyRead)
103+
+ _q_readyRead();
104+
+ if (needInvokeReceiveReply)
105+
+ _q_receiveReply();
106+
+ if (needInvokeSendRequest)
107+
+ sendRequest();
108+
+}
109+
+
110+
void QHttpNetworkConnectionChannel::requeueSpdyRequests()
111+
{
112+
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
113+
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
114+
index 6be0c51f9fe..613fda7bc31 100644
115+
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
116+
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
117+
@@ -107,6 +107,10 @@ public:
118+
QAbstractSocket *socket;
119+
bool ssl;
120+
bool isInitialized;
121+
+ bool waitingForPotentialAbort = false;
122+
+ bool needInvokeReceiveReply = false;
123+
+ bool needInvokeReadyRead = false;
124+
+ bool needInvokeSendRequest = false;
125+
ChannelState state;
126+
QHttpNetworkRequest request; // current request, only used for HTTP
127+
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
128+
@@ -187,6 +191,8 @@ public:
129+
void closeAndResendCurrentRequest();
130+
void resendCurrentRequest();
131+
132+
+ void checkAndResumeCommunication();
133+
+
134+
bool isSocketBusy() const;
135+
bool isSocketWriting() const;
136+
bool isSocketWaiting() const;
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
From 09e22c6c3280d4187b1ed2d979ceea478b7bed75 Mon Sep 17 00:00:00 2001
2+
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <marten.nordheim@qt.io>
3+
Date: Tue, 11 Aug 2020 17:20:03 +0200
4+
Subject: [PATCH] QNAM: Don't error out if the server doesn't support any ALPN
5+
we request
6+
7+
If we ask for HTTP/2 or 1.1 and the server doesn't list either then we
8+
should still try to connect using HTTP/1(.1) just in case, to keep
9+
compatibility.
10+
11+
Task-number: QTBUG-85902
12+
Change-Id: I6ff2e38ac9d767e482a19ee4c81d101be37d3fab
13+
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
14+
---
15+
From 62d85389a4a3ef22db80e721bf7c646a50874452 Mon Sep 17 00:00:00 2001
16+
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <marten.nordheim@qt.io>
17+
Date: Tue, 18 Aug 2020 12:10:16 +0200
18+
Subject: [PATCH] http: When falling back to http/1 use the socket's ssl config
19+
20+
And not the ssl configuration we have on the reply since it's missing
21+
e.g. the newly received session ticket.
22+
23+
Change-Id: Idfeb09012a847605a76d1fe4fb881c663d019b4a
24+
Reviewed-by: Peter Hartmann <peter@edelhirsch.io>
25+
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
26+
---
27+
From 95064c35826793c5d6a4edff9fa08ad308b047bb Mon Sep 17 00:00:00 2001
28+
From: Timur Pocheptsov <timur.pocheptsov@qt.io>
29+
Date: Tue, 20 Jul 2021 08:16:28 +0200
30+
Subject: [PATCH] H2: emit encrypted for at least the first reply, similar to
31+
H1
32+
MIME-Version: 1.0
33+
Content-Type: text/plain; charset=UTF-8
34+
Content-Transfer-Encoding: 8bit
35+
36+
Fixes: QTBUG-95277
37+
Change-Id: I1fe01503376c0d6278e366d7bd31b412b7cc3a69
38+
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
39+
(cherry picked from commit c23b7886348dc313ccec1a131850a7cce1b429de)
40+
---
41+
42+
src/network/access/qhttpnetworkconnectionchannel.cpp | 22 +++++++++----------
43+
1 file changed, 10 insertions(+), 12 deletions(-)
44+
45+
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
46+
index 1fac24ab..d078b194 100644
47+
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
48+
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
49+
@@ -1176,8 +1176,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
50+
// after establishing a secure connection we immediately start sending
51+
// HTTP/2 frames.
52+
switch (sslSocket->sslConfiguration().nextProtocolNegotiationStatus()) {
53+
- case QSslConfiguration::NextProtocolNegotiationNegotiated:
54+
- case QSslConfiguration::NextProtocolNegotiationUnsupported: {
55+
+ case QSslConfiguration::NextProtocolNegotiationNegotiated: {
56+
QByteArray nextProtocol = sslSocket->sslConfiguration().nextNegotiatedProtocol();
57+
if (nextProtocol == QSslConfiguration::NextProtocolHttp1_1) {
58+
// fall through to create a QHttpProtocolHandler
59+
@@ -1199,17 +1198,12 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
60+
}
61+
}
62+
Q_FALLTHROUGH();
63+
+ case QSslConfiguration::NextProtocolNegotiationUnsupported: // No agreement, try HTTP/1(.1)
64+
case QSslConfiguration::NextProtocolNegotiationNone: {
65+
protocolHandler.reset(new QHttpProtocolHandler(this));
66+
- if (!sslConfiguration.data()) {
67+
- // Our own auto-tests bypass the normal initialization (done by
68+
- // QHttpThreadDelegate), this means in the past we'd have here
69+
- // the default constructed QSslConfiguration without any protocols
70+
- // to negotiate. Let's create it now:
71+
- sslConfiguration.reset(new QSslConfiguration);
72+
- }
73+
74+
- QList<QByteArray> protocols = sslConfiguration->allowedNextProtocols();
75+
+ QSslConfiguration newConfiguration = sslSocket->sslConfiguration();
76+
+ QList<QByteArray> protocols = newConfiguration.allowedNextProtocols();
77+
const int nProtocols = protocols.size();
78+
// Clear the protocol that we failed to negotiate, so we do not try
79+
// it again on other channels that our connection can create/open.
80+
@@ -1219,10 +1213,10 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
81+
protocols.removeAll(QSslConfiguration::NextProtocolSpdy3_0);
82+
83+
if (nProtocols > protocols.size()) {
84+
- sslConfiguration->setAllowedNextProtocols(protocols);
85+
+ newConfiguration.setAllowedNextProtocols(protocols);
86+
const int channelCount = connection->d_func()->channelCount;
87+
for (int i = 0; i < channelCount; ++i)
88+
- connection->d_func()->channels[i].setSslConfiguration(*sslConfiguration);
89+
+ connection->d_func()->channels[i].setSslConfiguration(newConfiguration);
90+
}
91+
92+
connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeHTTP);
93+
@@ -1257,6 +1251,10 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
94+
connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
95+
// we call setSpdyWasUsed(true) on the replies in the SPDY handler when the request is sent
96+
if (spdyRequestsToSend.count() > 0) {
97+
+ // Similar to HTTP/1.1 counterpart below:
98+
+ const auto &pairs = spdyRequestsToSend.values(); // (request, reply)
99+
+ const auto &pair = pairs.first();
100+
+ emit pair.second->encrypted();
101+
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
102+
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
103+
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
104+
--
105+
2.25.1

SPECS/qt5-qtbase/qt5-qtbase.spec

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
Name: qt5-qtbase
3434
Summary: Qt5 - QtBase components
3535
Version: 5.12.11
36-
Release: 12%{?dist}
36+
Release: 13%{?dist}
3737
# See LICENSE.GPL3-EXCEPT.txt, for exception details
3838
License: GFDL AND LGPLv3 AND GPLv2 AND GPLv3 with exceptions AND QT License Agreement 4.0
3939
Vendor: Microsoft Corporation
@@ -159,6 +159,10 @@ Patch89: CVE-2021-38593.patch
159159
# Fix CVE-2022-25643
160160
Patch90: CVE-2022-25643.patch
161161

162+
# Fix CVE-2024-39936
163+
Patch91: qt5-qtbase-5.15-http-encrypted-signal.patch
164+
Patch92: CVE-2024-39936.patch
165+
162166
# Do not check any files in %%{_qt5_plugindir}/platformthemes/ for requires.
163167
# Those themes are there for platform integration. If the required libraries are
164168
# not there, the platform to integrate with isn't either. Then Qt will just
@@ -270,6 +274,8 @@ Qt5 libraries used for drawing widgets and OpenGL items.
270274
%patch88 -p1
271275
%patch89 -p1
272276
%patch90 -p1
277+
%patch91 -p1
278+
%patch92 -p1
273279

274280
## upstream patches
275281

@@ -775,6 +781,9 @@ fi
775781
%{_qt5_libdir}/cmake/Qt5Gui/Qt5Gui_QXdgDesktopPortalThemePlugin.cmake
776782

777783
%changelog
784+
* Wed Aug 07 2024 Sumedh Sharma <sumsharma@microsoft.com> - 5.12.11-13
785+
- Add patch to resolve CVE-2024-39936.
786+
778787
* Wed Mar 27 2024 Alberto David Perez Guevara <aperezguevar@microsoft.com> - 5.12.11-12
779788
- Add patch to resolve CVE-2022-25643.
780789

0 commit comments

Comments
 (0)