[qt5-base] add patch for CVE-2024-39936 (#40026)

This commit is contained in:
Carsten Grimm 2024-07-24 07:24:42 +02:00 committed by GitHub
parent 13fc727923
commit 6693fc7601
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 144 additions and 2 deletions

View file

@ -0,0 +1,136 @@
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index d1b5dfda2e2..ee04a1856c6 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -375,12 +375,12 @@ bool QHttp2ProtocolHandler::sendRequest()
}
}
- if (!prefaceSent && !sendClientPreface())
- return false;
-
if (!requests.size())
return true;
+ if (!prefaceSent && !sendClientPreface())
+ return false;
+
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
// Check what was promised/pushed, maybe we do not have to send a request
// and have a response already?
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index bd2f32e3528..6f3bd807a09 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -255,6 +255,10 @@ void QHttpNetworkConnectionChannel::abort()
bool QHttpNetworkConnectionChannel::sendRequest()
{
Q_ASSERT(!protocolHandler.isNull());
+ if (waitingForPotentialAbort) {
+ needInvokeSendRequest = true;
+ return false; // this return value is unused
+ }
return protocolHandler->sendRequest();
}
@@ -267,21 +271,28 @@ bool QHttpNetworkConnectionChannel::sendRequest()
void QHttpNetworkConnectionChannel::sendRequestDelayed()
{
QMetaObject::invokeMethod(this, [this] {
- Q_ASSERT(!protocolHandler.isNull());
if (reply)
- protocolHandler->sendRequest();
+ sendRequest();
}, Qt::ConnectionType::QueuedConnection);
}
void QHttpNetworkConnectionChannel::_q_receiveReply()
{
Q_ASSERT(!protocolHandler.isNull());
+ if (waitingForPotentialAbort) {
+ needInvokeReceiveReply = true;
+ return;
+ }
protocolHandler->_q_receiveReply();
}
void QHttpNetworkConnectionChannel::_q_readyRead()
{
Q_ASSERT(!protocolHandler.isNull());
+ if (waitingForPotentialAbort) {
+ needInvokeReadyRead = true;
+ return;
+ }
protocolHandler->_q_readyRead();
}
@@ -1289,7 +1300,18 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
// Similar to HTTP/1.1 counterpart below:
const auto &pairs = spdyRequestsToSend.values(); // (request, reply)
const auto &pair = pairs.first();
+ waitingForPotentialAbort = true;
emit pair.second->encrypted();
+
+ // We don't send or handle any received data until any effects from
+ // emitting encrypted() have been processed. This is necessary
+ // because the user may have called abort(). We may also abort the
+ // whole connection if the request has been aborted and there is
+ // no more requests to send.
+ QMetaObject::invokeMethod(this,
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
+ Qt::QueuedConnection);
+
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
@@ -1307,6 +1329,26 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
}
}
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
+{
+ Q_ASSERT(connection->connectionType() > QHttpNetworkConnection::ConnectionTypeHTTP);
+
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
+ // effects from emitting encrypted() have been processed.
+ // This function is called after encrypted() was emitted, so check for changes.
+
+ if (!reply && spdyRequestsToSend.isEmpty())
+ abort();
+ waitingForPotentialAbort = false;
+ if (needInvokeReadyRead)
+ _q_readyRead();
+ if (needInvokeReceiveReply)
+ _q_receiveReply();
+ if (needInvokeSendRequest)
+ sendRequest();
+}
+
void QHttpNetworkConnectionChannel::requeueSpdyRequests()
{
QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values();
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 6be0c51f9fe..613fda7bc31 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -107,6 +107,10 @@ public:
QAbstractSocket *socket;
bool ssl;
bool isInitialized;
+ bool waitingForPotentialAbort = false;
+ bool needInvokeReceiveReply = false;
+ bool needInvokeReadyRead = false;
+ bool needInvokeSendRequest = false;
ChannelState state;
QHttpNetworkRequest request; // current request, only used for HTTP
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
@@ -187,6 +191,8 @@ public:
void closeAndResendCurrentRequest();
void resendCurrentRequest();
+ void checkAndResumeCommunication();
+
bool isSocketBusy() const;
bool isSocketWriting() const;
bool isSocketWaiting() const;

View file

@ -55,6 +55,7 @@ qt_download_submodule( OUT_SOURCE_PATH SOURCE_PATH
patches/0001-CVE-2023-51714-qtbase-5.15.diff
patches/0002-CVE-2023-51714-qtbase-5.15.diff
patches/CVE-2024-25580-qtbase-5.15.diff
patches/CVE-2024-39936-qtbase-5.15.patch
patches/winmain_pro.patch #Moves qtmain to manual-link
patches/windows_prf.patch #fixes the qtmain dependency due to the above move

View file

@ -1,7 +1,7 @@
{
"name": "qt5-base",
"version": "5.15.14",
"port-version": 1,
"port-version": 2,
"description": "Qt Base provides the basic non-GUI functionality required by all Qt applications.",
"homepage": "https://www.qt.io/",
"license": null,

View file

@ -7238,7 +7238,7 @@
},
"qt5-base": {
"baseline": "5.15.14",
"port-version": 1
"port-version": 2
},
"qt5-canvas3d": {
"baseline": "0",

View file

@ -1,5 +1,10 @@
{
"versions": [
{
"git-tree": "70b9f2253a8552920bde3808c812936bcf4d66cd",
"version": "5.15.14",
"port-version": 2
},
{
"git-tree": "317554d7e9c175899b3595ef4eb6d54839348e38",
"version": "5.15.14",