From c9737f389b96f421091e71229989fb0b6a6e98ef Mon Sep 17 00:00:00 2001 From: wk333 <13474090681@163.com> Date: Tue, 26 Jul 2022 16:54:38 +0800 Subject: [PATCH] Fix CVE-2021-38593 and CVE-2022-25255 --- CVE-2021-38593.patch | 84 ++++++++++++++++++++++++++++++++++++++++ CVE-2022-25255.patch | 92 ++++++++++++++++++++++++++++++++++++++++++++ qt5-qtbase.spec | 10 ++++- 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 CVE-2021-38593.patch create mode 100644 CVE-2022-25255.patch diff --git a/CVE-2021-38593.patch b/CVE-2021-38593.patch new file mode 100644 index 0000000..6f5d939 --- /dev/null +++ b/CVE-2021-38593.patch @@ -0,0 +1,84 @@ +Description: avoid processing-intensive painting of high number of tiny dashes + When stroking a dashed path, an unnecessary amount of processing would + be spent if there is a huge number of dashes visible, e.g. because of + scaling. Since the dashes are too small to be individually visible + anyway, just replace with a semi-transparent solid line for such + cases. +Origin: upstream, commits: + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=f4d791b330d02777 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=6b400e3147dcfd8c + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=84aba80944a2e1c3 + https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c +Last-Update: 2021-11-27 + +--- a/src/gui/painting/qpaintengineex.cpp ++++ b/src/gui/painting/qpaintengineex.cpp +@@ -385,10 +385,10 @@ QPainterState *QPaintEngineEx::createSta + + Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp + +-void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) ++void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen) + { + #ifdef QT_DEBUG_DRAW +- qDebug() << "QPaintEngineEx::stroke()" << pen; ++ qDebug() << "QPaintEngineEx::stroke()" << inPen; + #endif + + Q_D(QPaintEngineEx); +@@ -403,6 +403,38 @@ void QPaintEngineEx::stroke(const QVecto + d->stroker.setCubicToHook(qpaintengineex_cubicTo); + } + ++ QRectF clipRect; ++ QPen pen = inPen; ++ if (pen.style() > Qt::SolidLine) { ++ QRectF cpRect = path.controlPointRect(); ++ const QTransform &xf = state()->matrix; ++ if (qt_pen_is_cosmetic(pen, state()->renderHints)) { ++ clipRect = d->exDeviceRect; ++ cpRect.translate(xf.dx(), xf.dy()); ++ } else { ++ clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect)); ++ } ++ // Check to avoid generating unwieldy amount of dashes that will not be visible anyway ++ qreal pw = pen.widthF() ? pen.widthF() : 1; ++ QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect; ++ qreal extent = qMax(extentRect.width(), extentRect.height()); ++ qreal patternLength = 0; ++ const QVector pattern = pen.dashPattern(); ++ const int patternSize = qMin(pattern.size(), 32); ++ for (int i = 0; i < patternSize; i++) ++ patternLength += qMax(pattern.at(i), qreal(0)); ++ patternLength *= pw; ++ if (qFuzzyIsNull(patternLength)) { ++ pen.setStyle(Qt::NoPen); ++ } else if (extent / patternLength > 10000) { ++ // approximate stream of tiny dashes with semi-transparent solid line ++ pen.setStyle(Qt::SolidLine); ++ QColor color(pen.color()); ++ color.setAlpha(color.alpha() / 2); ++ pen.setColor(color); ++ } ++ } ++ + if (!qpen_fast_equals(pen, d->strokerPen)) { + d->strokerPen = pen; + d->stroker.setJoinStyle(pen.joinStyle()); +@@ -430,14 +462,8 @@ void QPaintEngineEx::stroke(const QVecto + return; + } + +- if (pen.style() > Qt::SolidLine) { +- if (qt_pen_is_cosmetic(pen, state()->renderHints)){ +- d->activeStroker->setClipRect(d->exDeviceRect); +- } else { +- QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); +- d->activeStroker->setClipRect(clipRect); +- } +- } ++ if (!clipRect.isNull()) ++ d->activeStroker->setClipRect(clipRect); + + if (d->activeStroker == &d->stroker) + d->stroker.setForceOpen(path.hasExplicitOpen()); diff --git a/CVE-2022-25255.patch b/CVE-2022-25255.patch new file mode 100644 index 0000000..764e939 --- /dev/null +++ b/CVE-2022-25255.patch @@ -0,0 +1,92 @@ +Description: QProcess: ensure we don't accidentally execute something from CWD + Unless "." (or the empty string) is in $PATH, we're not supposed to find + executables in the current directory. This is how the Unix shells behave + and we match their behavior. It's also the behavior Qt had prior to 5.9 + (commit 28666d167aa8e602c0bea25ebc4d51b55005db13). On Windows, searching + the current directory is the norm, so we keep that behavior. + . + This commit does not add an explicit check for an empty return from + QStandardPaths::findExecutable(). Instead, we allow that empty string to + go all the way to execve(2), which will fail with ENOENT. We could catch + it early, before fork(2), but why add code for the error case? + . + See https://kde.org/info/security/advisory-20220131-1.txt +Origin: upstream, https://download.qt.io/official_releases/qt/5.15/CVE-2022-25255-qprocess5-15.diff +Last-Update: 2022-02-21 + +--- a/src/corelib/io/qprocess_unix.cpp ++++ b/src/corelib/io/qprocess_unix.cpp +@@ -1,7 +1,7 @@ + /**************************************************************************** + ** + ** Copyright (C) 2016 The Qt Company Ltd. +-** Copyright (C) 2016 Intel Corporation. ++** Copyright (C) 2022 Intel Corporation. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the QtCore module of the Qt Toolkit. +@@ -422,14 +422,15 @@ void QProcessPrivate::startProcess() + // Add the program name to the argument list. + argv[0] = nullptr; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) { +- const QByteArray &tmp = QFile::encodeName(exeFilePath); +- argv[0] = ::strdup(tmp.constData()); +- } +- } +- if (!argv[0]) ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { + argv[0] = ::strdup(encodedProgramName.constData()); ++ } + + // Add every argument to the list + for (int i = 0; i < arguments.count(); ++i) +@@ -983,15 +984,16 @@ bool QProcessPrivate::startDetached(qint + envp = _q_dupEnvironment(environment.d.constData()->vars, &envc); + } + +- QByteArray tmp; + if (!program.contains(QLatin1Char('/'))) { ++ // findExecutable() returns its argument if it's an absolute path, ++ // otherwise it searches $PATH; returns empty if not found (we handle ++ // that case much later) + const QString &exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) +- tmp = QFile::encodeName(exeFilePath); ++ const QByteArray &tmp = QFile::encodeName(exeFilePath); ++ argv[0] = ::strdup(tmp.constData()); ++ } else { ++ argv[0] = ::strdup(QFile::encodeName(program)); + } +- if (tmp.isEmpty()) +- tmp = QFile::encodeName(program); +- argv[0] = tmp.data(); + + if (envp) + qt_safe_execve(argv[0], argv, envp); +--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp ++++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +@@ -1449,7 +1449,7 @@ void tst_QApplication::desktopSettingsAw + { + #if QT_CONFIG(process) + QProcess testProcess; +- testProcess.start("desktopsettingsaware_helper"); ++ testProcess.start("./desktopsettingsaware_helper"); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'desktopsettingsaware_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(10000)); +@@ -2365,7 +2365,7 @@ void tst_QApplication::qtbug_12673() + #if QT_CONFIG(process) + QProcess testProcess; + QStringList arguments; +- testProcess.start("modal_helper", arguments); ++ testProcess.start("./modal_helper", arguments); + QVERIFY2(testProcess.waitForStarted(), + qPrintable(QString::fromLatin1("Cannot start 'modal_helper': %1").arg(testProcess.errorString()))); + QVERIFY(testProcess.waitForFinished(20000)); diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec index e550c59..62b798f 100644 --- a/qt5-qtbase.spec +++ b/qt5-qtbase.spec @@ -34,7 +34,7 @@ BuildRequires: pkgconfig(libsystemd) Name: qt5-qtbase Summary: Qt5 - QtBase components Version: 5.15.2 -Release: 1 +Release: 2 # See LGPL_EXCEPTIONS.txt, for exception details @@ -118,6 +118,9 @@ Patch0015: qtbase-QTBUG-89977.patch Patch0016: qtbase-filechooser-portal-send-window-id-in-hex.patch Patch0017: qtbase-QTBUG-91909.patch Patch0018: 0001-modify-kwin_5.18-complier-error.patch +# https://launchpad.net/ubuntu/+source/qtbase-opensource-src/5.15.2+dfsg-15 +Patch0019: CVE-2021-38593.patch +Patch0020: CVE-2022-25255.patch # Do not check any files in %%{_qt5_plugindir}/platformthemes/ for requires. # Those themes are there for platform integration. If the required libraries are # not there, the platform to integrate with isn't either. Then Qt will just @@ -371,6 +374,8 @@ Qt5 libraries used for drawing widgets and OpenGL items. %patch0015 -p1 -b .QTBUG-89977 %patch0017 -p1 -b .QTBUG-91909 %patch0018 -p1 +%patch0019 -p1 +%patch0020 -p1 # move some bundled libs to ensure they're not accidentally used pushd src/3rdparty mkdir UNUSED @@ -1012,6 +1017,9 @@ fi %changelog +* Tue Jul 26 2022 wangkai - 5.15.2-2 +- Fix CVE-2021-38593 and CVE-2022-25255 + * Sat Dec 11 2021 hua_yadong - 5.15.2-1 - update to upstream version 5.15.2 -- Gitee