diff --git a/0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch b/0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch new file mode 100644 index 0000000..f9f74b1 --- /dev/null +++ b/0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch @@ -0,0 +1,211 @@ +From a5bf4641b066de4c7ccf1a0e909abe8d9ced3cda Mon Sep 17 00:00:00 2001 +From: Thiago Macieira +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 +Reviewed-by: MÃ¥rten Nordheim +Reviewed-by: Thiago Macieira +--- + src/corelib/io/qprocess_unix.cpp | 9 +- + .../auto/corelib/io/qprocess/tst_qprocess.cpp | 93 ++++++++++++++++++- + .../kernel/qapplication/tst_qapplication.cpp | 4 +- + 3 files changed, 99 insertions(+), 7 deletions(-) + +diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp +index bf19fc2..3a2e5cf 100644 +--- a/src/corelib/io/qprocess_unix.cpp ++++ b/src/corelib/io/qprocess_unix.cpp +@@ -1,7 +1,7 @@ + /**************************************************************************** + ** + ** Copyright (C) 2020 The Qt Company Ltd. +-** Copyright (C) 2021 Intel Corporation. ++** Copyright (C) 2022 Intel Corporation. + ** Copyright (C) 2021 Alex Trotsenko. + ** Contact: https://www.qt.io/licensing/ + ** +@@ -437,9 +437,10 @@ static QString resolveExecutable(const QString &program) + #endif + + if (!program.contains(QLatin1Char('/'))) { +- QString exeFilePath = QStandardPaths::findExecutable(program); +- if (!exeFilePath.isEmpty()) +- return exeFilePath; ++ // 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) ++ return QStandardPaths::findExecutable(program); + } + return program; + } +diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +index 63f2a81..80005a7 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) 2021 The Qt Company Ltd. +-** Copyright (C) 2020 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. +@@ -151,6 +151,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) +@@ -2524,5 +2526,94 @@ void tst_QProcess::processEventsInAReadyReadSlot() + QVERIFY(process.waitForFinished()); + } + ++enum class ChdirMode { ++ None = 0, ++ InParent, ++ InChild ++}; ++Q_DECLARE_METATYPE(ChdirMode) ++ ++void tst_QProcess::startFromCurrentWorkingDir_data() ++{ ++ qRegisterMetaType(); ++ QTest::addColumn("programPrefix"); ++ QTest::addColumn("chdirMode"); ++ QTest::addColumn("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(); ++ 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" +diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +index e5ac69a..b0dd14a 100644 +--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp ++++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +@@ -1530,7 +1530,7 @@ void tst_QApplication::desktopSettingsAware() + environment += QLatin1String("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM=1"); + testProcess.setEnvironment(environment); + #endif +- 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)); +@@ -2470,7 +2470,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)); +-- +2.35.1 + diff --git a/qt6-base.changes b/qt6-base.changes index c0e87e6..5fa0c4b 100644 --- a/qt6-base.changes +++ b/qt6-base.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Wed Mar 2 09:16:10 UTC 2022 - Christophe Giboudeaux + +- Add upstream change (boo#1196501, CVE-2022-25255): + * 0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch +- Install qt6-core-private-devel when installing qt6-core-devel + (boo#1195368) + ------------------------------------------------------------------- Mon Jan 31 08:54:21 UTC 2022 - Christophe Giboudeaux diff --git a/qt6-base.spec b/qt6-base.spec index a39bd40..40102cd 100644 --- a/qt6-base.spec +++ b/qt6-base.spec @@ -39,6 +39,7 @@ URL: https://www.qt.io Source: https://download.qt.io/official_releases/qt/%{short_version}/%{real_version}%{tar_suffix}/submodules/%{tar_name}-%{real_version}%{tar_suffix}.tar.xz Source99: qt6-base-rpmlintrc # Patches 0-100 are upstream patches # +Patch0: 0001-QProcess-Unix-ensure-we-don-t-accidentally-execute-s.patch # Patches 100-200 are openSUSE and/or non-upstream(able) patches # Patch100: 0001-Tell-the-truth-about-private-API.patch %if 0%{?suse_version} == 1500 @@ -232,6 +233,9 @@ Requires: qt6-base-common-devel = %{version} # Some public classes require C++ 17 features Requires: gcc10-c++ %endif +# boo#1195368 +# TODO: move the pri file into qt6-core-devel when 6.2.4 is out +%requires_eq qt6-core-private-devel %description -n qt6-core-devel Development files for the Qt 6 Core library. @@ -786,8 +790,8 @@ rm %{buildroot}%{_qt6_mkspecsdir}/modules/qt_lib_concurrent_private.pri rm %{buildroot}%{_qt6_mkspecsdir}/modules/qt_lib_openglwidgets_private.pri # These files are only useful for the Qt continuous integration -rm %{buildroot}%{_qt6_libexecdir}/ensure_pro_file.cmake rm %{buildroot}%{_qt6_libexecdir}/android_*.sh +rm %{buildroot}%{_qt6_libexecdir}/ensure_pro_file.cmake # This is only for Apple platforms and has a python2 dep rm -r %{buildroot}%{_qt6_mkspecsdir}/features/uikit