Fix CVE-2021-38593 and CVE-2022-25255

(cherry picked from commit fb537edb24b6d18187c0d177fd0d6c22423a70b3)
This commit is contained in:
wk333 2022-07-26 17:25:43 +08:00 committed by openeuler-sync-bot
parent 394a64ea52
commit cbc3e7276e
3 changed files with 311 additions and 1 deletions

84
CVE-2021-38593.patch Normal file
View File

@ -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=7f345f2a1c8d9f60
https://code.qt.io/cgit/qt/qtbase.git/commit/?id=9378ba2ae857df7e
https://code.qt.io/cgit/qt/qtbase.git/commit/?id=81998f50d039a631
https://code.qt.io/cgit/qt/qtbase.git/commit/?id=cca8ed0547405b1c
Last-Update: 2021-12-12
--- 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<qreal> 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);
const QPainterPath::ElementType *types = path.elements();
const qreal *points = path.points();

219
CVE-2022-25255.patch Normal file
View File

@ -0,0 +1,219 @@
From ab3e0383b9de49c61bc49f5fbef80d1409fcafde Mon Sep 17 00:00:00 2001
From: Thiago Macieira <thiago.macieira@intel.com>
Date: Mon, 31 Jan 2022 11:00:19 -0800
Subject: [PATCH] QProcess/Unix: ensure we don't accidentally execute something
from CWD
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
[ChangeLog][Important Behavior Changes] When passed a simple program
name with no slashes, QProcess on Unix systems will now only search the
current directory if "." is one of the entries in the PATH environment
variable. This bug fix restores the behavior QProcess had before Qt 5.9.
If launching an executable in the directory set by setWorkingDirectory()
or inherited from the parent is intended, pass a program name starting
with "./". For more information and best practices about finding an
executable, see QProcess' documentation.
Pick-to: 5.15 6.2 6.3
Change-Id: I54f205f6b7314351b078fffd16cf7013c97ee9fb
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 29fceed2ffb41954a63001414bd042611f2d4980)
Note: This currently breaks various autotests, as they rely on the test
helpers (same directory as the test) to be in $PATH. In Qt 6, the CMake
test code sets this explicitly, which is not the case in Qt 5 (yet).
---
src/corelib/io/qprocess_unix.cpp | 24 ++---
.../auto/corelib/io/qprocess/tst_qprocess.cpp | 93 ++++++++++++++++++-
.../kernel/qapplication/tst_qapplication.cpp | 4 +-
3 files changed, 107 insertions(+), 14 deletions(-)
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 50390e57f5..5bd3b7f297 100644
--- 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)
@@ -985,11 +986,12 @@ bool QProcessPrivate::startDetached(qint64 *pid)
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);
- }
- if (tmp.isEmpty())
+ tmp = QFile::encodeName(exeFilePath);
+ } else
tmp = QFile::encodeName(program);
argv[0] = tmp.data();
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index bc9df3f1f3..33051d3803 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.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 test suite of the Qt Toolkit.
@@ -149,6 +149,8 @@ private slots:
void startStopStartStopBuffers();
void processEventsInAReadyReadSlot_data();
void processEventsInAReadyReadSlot();
+ void startFromCurrentWorkingDir_data();
+ void startFromCurrentWorkingDir();
// keep these at the end, since they use lots of processes and sometimes
// caused obscure failures to occur in tests that followed them (esp. on the Mac)
@@ -2732,5 +2734,94 @@ void tst_QProcess::finishProcessBeforeReadingDone_deprecated()
QVERIFY(process.waitForFinished());
}
+enum class ChdirMode {
+ None = 0,
+ InParent,
+ InChild
+};
+Q_DECLARE_METATYPE(ChdirMode)
+
+void tst_QProcess::startFromCurrentWorkingDir_data()
+{
+ qRegisterMetaType<ChdirMode>();
+ QTest::addColumn<QString>("programPrefix");
+ QTest::addColumn<ChdirMode>("chdirMode");
+ QTest::addColumn<bool>("success");
+
+ constexpr bool IsWindows = true
+#ifdef Q_OS_UNIX
+ && false
+#endif
+ ;
+
+ // baseline: trying to execute the directory, this can't possibly succeed!
+ QTest::newRow("plain-same-cwd") << QString() << ChdirMode::None << false;
+
+ // cross-platform behavior: neither OS searches the setWorkingDirectory()
+ // dir without "./"
+ QTest::newRow("plain-child-chdir") << QString() << ChdirMode::InChild << false;
+
+ // cross-platform behavior: both OSes search the parent's CWD with "./"
+ QTest::newRow("prefixed-parent-chdir") << "./" << ChdirMode::InParent << true;
+
+ // opposite behaviors: Windows searches the parent's CWD and Unix searches
+ // the child's with "./"
+ QTest::newRow("prefixed-child-chdir") << "./" << ChdirMode::InChild << !IsWindows;
+
+ // Windows searches the parent's CWD without "./"
+ QTest::newRow("plain-parent-chdir") << QString() << ChdirMode::InParent << IsWindows;
+}
+
+void tst_QProcess::startFromCurrentWorkingDir()
+{
+ QFETCH(QString, programPrefix);
+ QFETCH(ChdirMode, chdirMode);
+ QFETCH(bool, success);
+
+ QProcess process;
+ qRegisterMetaType<QProcess::ProcessError>();
+ QSignalSpy errorSpy(&process, &QProcess::errorOccurred);
+ QVERIFY(errorSpy.isValid());
+
+ // both the dir name and the executable name
+ const QString target = QStringLiteral("testProcessNormal");
+ process.setProgram(programPrefix + target);
+
+#ifdef Q_OS_UNIX
+ // Reset PATH, to be sure it doesn't contain . or the empty path.
+ // We can't do this on Windows because DLLs are searched in PATH
+ // and Windows always searches "." anyway.
+ auto restoreEnv = qScopeGuard([old = qgetenv("PATH")] {
+ qputenv("PATH", old);
+ });
+ qputenv("PATH", "/");
+#endif
+
+ switch (chdirMode) {
+ case ChdirMode::InParent: {
+ auto restoreCwd = qScopeGuard([old = QDir::currentPath()] {
+ QDir::setCurrent(old);
+ });
+ QVERIFY(QDir::setCurrent(target));
+ process.start();
+ break;
+ }
+ case ChdirMode::InChild:
+ process.setWorkingDirectory(target);
+ Q_FALLTHROUGH();
+ case ChdirMode::None:
+ process.start();
+ break;
+ }
+
+ QCOMPARE(process.waitForStarted(), success);
+ QCOMPARE(errorSpy.count(), int(!success));
+ if (success) {
+ QVERIFY(process.waitForFinished());
+ } else {
+ QCOMPARE(process.error(), QProcess::FailedToStart);
+ }
+}
+
QTEST_MAIN(tst_QProcess)
#include "tst_qprocess.moc"
--
2.34.0

View File

@ -13,7 +13,7 @@
Name: qt5-qtbase
Summary: Core component of Qt toolkit
Version: 5.11.1
Release: 12
Release: 13
License: LGPLv2 with exceptions or GPLv3 with exceptions
Url: http://qt-project.org/
Source0: https://download.qt.io/new_archive/qt/5.11/%{version}/submodules/qtbase-everywhere-src-%{version}.tar.xz
@ -37,6 +37,10 @@ Patch0011: qt5-qtbase-glibc.patch
Patch6000: CVE-2018-15518.patch
Patch6001: CVE-2015-9541.patch
Patch6002: CVE-2019-18281.patch
# https://launchpad.net/ubuntu/+source/qtbase-opensource-src/5.12.8+dfsg-0ubuntu2.1
Patch6003: CVE-2021-38593.patch
# https://build.opensuse.org/package/view_file/SUSE:SLE-15-SP3:Update/libqt5-qtbase/0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch?expand=1
Patch6004: CVE-2022-25255.patch
BuildRequires: pkgconfig(libsystemd) cups-devel desktop-file-utils findutils
BuildRequires: libjpeg-devel libmng-devel libtiff-devel pkgconfig(alsa)
@ -403,6 +407,9 @@ fi
%changelog
* Tue Jul 26 2022 wangkai <wangkai385@h-partners.com> - 5.11.1-13
- Fix CVE-2021-38593 and CVE-2022-25255
* Thu Apr 22 2021 wangyue <wangyue92@huawei.com> - 5.11.1-12
- fix CVE-2019-18281