From 4a9cc7f9009fa45681de5916b05290b5563a211bb603546361149e3c760ada63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 7 Feb 2025 11:11:41 +0100 Subject: [PATCH] Sync from SUSE:SLFO:Main qt6-connectivity revision 0b033aaba2f6f00593f084c3ec1ef560 --- ...llerPrivateBluez-guard-against-malfo.patch | 226 ++++++++++++++++++ qt6-connectivity.changes | 29 +++ qt6-connectivity.spec | 15 +- qtconnectivity-everywhere-src-6.7.2.tar.xz | 3 - qtconnectivity-everywhere-src-6.8.1.tar.xz | 3 + 5 files changed, 267 insertions(+), 9 deletions(-) create mode 100644 0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch delete mode 100644 qtconnectivity-everywhere-src-6.7.2.tar.xz create mode 100644 qtconnectivity-everywhere-src-6.8.1.tar.xz diff --git a/0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch b/0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch new file mode 100644 index 0000000..35208e2 --- /dev/null +++ b/0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch @@ -0,0 +1,226 @@ +From 465e3f3112a9c158aa6dd2f8b9439ae6c2de336f Mon Sep 17 00:00:00 2001 +From: Ivan Solovev +Date: Thu, 2 Jan 2025 16:48:49 +0100 +Subject: [PATCH] QLowEnergyControllerPrivateBluez: guard against malformed + replies + +The QLowEnergyControllerPrivateBluez::l2cpReadyRead() slot reads the +data from a Bluetooth L2CAP socket and then tries to process it +according to ATT protocol specs. + +However, the code was missing length and sanity checks at some +codepaths in processUnsolicitedReply() and processReply() helper +methods, simply relying on the data to be in the proper format. + +This patch adds some minimal checks to make sure that we do not read +past the end of the received array and do not divide by zero. + +This problem was originally pointed out by Marc Mutz in an unrelated +patch. + +Pick-to: 6.5 5.15 +Change-Id: I8dcfe031f70ad61fa3d87dc9d771c3fabc6d0edc +Reviewed-by: Alex Blasche +Reviewed-by: Juha Vuolle +(cherry picked from commit aecbd657c841a2a8c74631ceac96b8ff1f03ab5c) +Reviewed-by: Qt Cherry-pick Bot +(cherry picked from commit 53e991671f725c136e9aa824c59ec13934c63fb4) +--- + src/bluetooth/qlowenergycontroller_bluez.cpp | 75 +++++++++++++++++--- + 1 file changed, 66 insertions(+), 9 deletions(-) + +diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp +index 6f0c9858..2bd0cb68 100644 +--- a/src/bluetooth/qlowenergycontroller_bluez.cpp ++++ b/src/bluetooth/qlowenergycontroller_bluez.cpp +@@ -64,14 +64,15 @@ using namespace QBluetooth; + + const int maxPrepareQueueSize = 1024; + +-static void dumpErrorInformation(const QByteArray &response) ++/* returns false if the format is incorrect */ ++static bool dumpErrorInformation(const QByteArray &response) + { + const char *data = response.constData(); + if (response.size() != 5 + || (static_cast(data[0]) + != QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE)) { + qCWarning(QT_BT_BLUEZ) << QLatin1String("Not a valid error response"); +- return; ++ return false; + } + + QBluezConst::AttCommand lastCommand = static_cast(data[1]); +@@ -126,6 +127,8 @@ static void dumpErrorInformation(const QByteArray &response) + + qCDebug(QT_BT_BLUEZ) << "Error:" << errorCode << "Error description:" << errorString + << "last command:" << lastCommand << "handle:" << handle; ++ ++ return true; + } + + static int getUuidSize(const QBluetoothUuid &uuid) +@@ -903,6 +906,7 @@ QLowEnergyHandle parseReadByTypeCharDiscovery( + { + Q_ASSERT(charData); + Q_ASSERT(data); ++ Q_ASSERT(elementLength >= 5); + + QLowEnergyHandle attributeHandle = bt_get_le16(&data[0]); + charData->properties = +@@ -912,7 +916,7 @@ QLowEnergyHandle parseReadByTypeCharDiscovery( + // Bluetooth LE data comes as little endian + if (elementLength == 7) // 16 bit uuid + charData->uuid = QBluetoothUuid(bt_get_le16(&data[5])); +- else ++ else if (elementLength == 21) // 128 bit uuid + charData->uuid = QUuid::fromBytes(&data[5], QSysInfo::LittleEndian); + + qCDebug(QT_BT_BLUEZ) << "Found handle:" << Qt::hex << attributeHandle +@@ -929,6 +933,7 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery( + { + Q_ASSERT(foundServices); + Q_ASSERT(data); ++ Q_ASSERT(elementLength >= 6); + + QLowEnergyHandle attributeHandle = bt_get_le16(&data[0]); + +@@ -938,9 +943,14 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery( + // data[2] -> included service start handle + // data[4] -> included service end handle + ++ // TODO: Spec v. 5.3, Vol. 3, Part G, 4.5.1 mentions that only ++ // 16-bit UUID can be returned here. If the UUID is 128-bit, ++ // then it is omitted from the response, and should be requested ++ // separately with the ATT_READ_REQ command. ++ + if (elementLength == 8) //16 bit uuid + foundServices->append(QBluetoothUuid(bt_get_le16(&data[6]))); +- else ++ else if (elementLength == 22) // 128 bit uuid + foundServices->append(QUuid::fromBytes(&data[6], QSysInfo::LittleEndian)); + + qCDebug(QT_BT_BLUEZ) << "Found included service: " << Qt::hex +@@ -949,17 +959,29 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery( + return attributeHandle; + } + ++Q_DECL_COLD_FUNCTION ++static void reportMalformedData(QBluezConst::AttCommand cmd, const QByteArray &response) ++{ ++ qCDebug(QT_BT_BLUEZ, "%s malformed data: %s", qt_getEnumName(cmd), ++ response.toHex().constData()); ++} ++ + void QLowEnergyControllerPrivateBluez::processReply( + const Request &request, const QByteArray &response) + { + Q_Q(QLowEnergyController); + ++ // We already have an isEmpty() check at the only calling site that reads ++ // incoming data, so Q_ASSERT is enough. ++ Q_ASSERT(!response.isEmpty()); ++ + QBluezConst::AttCommand command = static_cast(response.constData()[0]); + + bool isErrorResponse = false; + // if error occurred 2. byte is previous request type + if (command == QBluezConst::AttCommand::ATT_OP_ERROR_RESPONSE) { +- dumpErrorInformation(response); ++ if (!dumpErrorInformation(response)) ++ return; + command = static_cast(response.constData()[1]); + isErrorResponse = true; + } +@@ -972,6 +994,10 @@ void QLowEnergyControllerPrivateBluez::processReply( + if (isErrorResponse) { + mtuSize = ATT_DEFAULT_LE_MTU; + } else { ++ if (response.size() < 3) { ++ reportMalformedData(command, response); ++ break; ++ } + const char *data = response.constData(); + quint16 mtu = bt_get_le16(&data[1]); + mtuSize = mtu; +@@ -1000,8 +1026,15 @@ void QLowEnergyControllerPrivateBluez::processReply( + break; + } + ++ // response[1] == elementLength. According to the spec it should be ++ // at least 4 bytes. See Spec v5.3, Vol 3, Part F, 3.4.4.10 ++ if (response.size() < 2 || response[1] < 4) { ++ reportMalformedData(command, response); ++ break; ++ } ++ + QLowEnergyHandle start = 0, end = 0; +- const quint16 elementLength = response.constData()[1]; ++ const quint16 elementLength = response.constData()[1]; // value checked above + const quint16 numElements = (response.size() - 2) / elementLength; + quint16 offset = 2; + const char *data = response.constData(); +@@ -1077,16 +1110,25 @@ void QLowEnergyControllerPrivateBluez::processReply( + } + + /* packet format: +- * if GATT_CHARACTERISTIC discovery ++ * if GATT_CHARACTERISTIC discovery (Spec 5.3, Vol. 3, Part G, 4.6) + * + * []+ ++ * The minimum elementLength is 7 bytes (uuid is always included) + * +- * if GATT_INCLUDE discovery ++ * if GATT_INCLUDE discovery (Spec 5.3, Vol. 3, Part G, 4.5.1) + * + * []+ ++ * The minimum elementLength is 6 bytes (uuid can be omitted). + * + * The uuid can be 16 or 128 bit. + */ ++ ++ const quint8 minimumElementLength = attributeType == GATT_CHARACTERISTIC ? 7 : 6; ++ if (response.size() < 2 || response[1] < minimumElementLength) { ++ reportMalformedData(command, response); ++ break; ++ } ++ + QLowEnergyHandle lastHandle; + const quint16 elementLength = response.constData()[1]; + const quint16 numElements = (response.size() - 2) / elementLength; +@@ -1283,6 +1325,12 @@ void QLowEnergyControllerPrivateBluez::processReply( + break; + } + ++ // Spec 5.3, Vol. 3, Part F, 3.4.3.2 ++ if (response.size() < 6) { ++ reportMalformedData(command, response); ++ break; ++ } ++ + const quint8 format = response[1]; + quint16 elementLength; + switch (format) { +@@ -1720,9 +1768,18 @@ void QLowEnergyControllerPrivateBluez::discoverServiceDescriptors( + + void QLowEnergyControllerPrivateBluez::processUnsolicitedReply(const QByteArray &payload) + { ++ Q_ASSERT(!payload.isEmpty()); ++ + const char *data = payload.constData(); +- bool isNotification = (static_cast(data[0]) ++ const auto command = static_cast(data[0]); ++ bool isNotification = (command + == QBluezConst::AttCommand::ATT_OP_HANDLE_VAL_NOTIFICATION); ++ ++ if (payload.size() < 3) { ++ reportMalformedData(command, payload); ++ return; ++ } ++ + const QLowEnergyHandle changedHandle = bt_get_le16(&data[1]); + + if (QT_BT_BLUEZ().isDebugEnabled()) { +-- +2.48.1 + diff --git a/qt6-connectivity.changes b/qt6-connectivity.changes index 071277c..d60e15e 100644 --- a/qt6-connectivity.changes +++ b/qt6-connectivity.changes @@ -1,3 +1,32 @@ +------------------------------------------------------------------- +Wed Jan 22 16:47:21 UTC 2025 - Antonio Larrosa + +- Fix license. It's using GPL-3.0-only not GPL-3.0-or-later + +------------------------------------------------------------------- +Wed Jan 22 09:08:10 UTC 2025 - Christophe Marin + +- Add security fix (CVE-2025-23050, boo#1236237) + * 0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch + +------------------------------------------------------------------- +Mon Dec 2 13:01:59 UTC 2024 - Christophe Marin + +- Update to 6.8.1: + * https://www.qt.io/blog/qt-6.8.1-released + +------------------------------------------------------------------- +Tue Oct 8 09:29:41 UTC 2024 - Christophe Marin + +- Update to 6.8.0: + * https://www.qt.io/blog/qt-6.8-released + +------------------------------------------------------------------- +Sat Sep 28 08:22:56 UTC 2024 - Christophe Marin + +- Update to 6.7.3 + * https://www.qt.io/blog/qt-6.7.3-released + ------------------------------------------------------------------- Wed Jun 19 07:25:40 UTC 2024 - Christophe Marin diff --git a/qt6-connectivity.spec b/qt6-connectivity.spec index 54f8478..b04ad6e 100644 --- a/qt6-connectivity.spec +++ b/qt6-connectivity.spec @@ -1,7 +1,7 @@ # # spec file for package qt6-connectivity # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,8 +16,8 @@ # -%define real_version 6.7.2 -%define short_version 6.7 +%define real_version 6.8.1 +%define short_version 6.8 %define tar_name qtconnectivity-everywhere-src %define tar_suffix %{nil} # @@ -27,13 +27,15 @@ %endif # Name: qt6-connectivity%{?pkg_suffix} -Version: 6.7.2 +Version: 6.8.1 Release: 0 Summary: Qt 6 connectivity tools and libraries -License: LGPL-3.0-only OR (GPL-2.0-only OR GPL-3.0-or-later) +License: GPL-2.0-only OR LGPL-3.0-only OR GPL-3.0-only URL: https://www.qt.io Source0: https://download.qt.io/official_releases/qt/%{short_version}/%{real_version}%{tar_suffix}/submodules/%{tar_name}-%{real_version}%{tar_suffix}.tar.xz Source99: qt6-connectivity-rpmlintrc +# PATCH-FIX-UPSTREAM +Patch0: 0001-QLowEnergyControllerPrivateBluez-guard-against-malfo.patch BuildRequires: pkgconfig BuildRequires: qt6-core-private-devel BuildRequires: qt6-network-private-devel @@ -101,7 +103,8 @@ The packages that build against these have to require the exact Qt version. %autosetup -p1 -n %{tar_name}-%{real_version}%{tar_suffix} %build -%cmake_qt6 +%cmake_qt6 \ + -DQT_GENERATE_SBOM:BOOL=FALSE %{qt6_build} diff --git a/qtconnectivity-everywhere-src-6.7.2.tar.xz b/qtconnectivity-everywhere-src-6.7.2.tar.xz deleted file mode 100644 index 5e34a96..0000000 --- a/qtconnectivity-everywhere-src-6.7.2.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8ed321b242f0e956473a295fa31670271f9b3acb797508644cb740f89f6c08e8 -size 1061952 diff --git a/qtconnectivity-everywhere-src-6.8.1.tar.xz b/qtconnectivity-everywhere-src-6.8.1.tar.xz new file mode 100644 index 0000000..ca5eaa9 --- /dev/null +++ b/qtconnectivity-everywhere-src-6.8.1.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccfd46e7ad2290710788274e145fb1f224d8a5ce360764ec10824b5908a6441c +size 1067952