public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] repo/gentoo:master commit in: kde-apps/kcron/files/, kde-apps/kcron/
@ 2022-02-16 18:58 Andreas Sturmlechner
  0 siblings, 0 replies; only message in thread
From: Andreas Sturmlechner @ 2022-02-16 18:58 UTC (permalink / raw
  To: gentoo-commits

commit:     f560da8a6e7041b35277af4f5b6576cd6799ee7f
Author:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
AuthorDate: Wed Feb 16 18:46:51 2022 +0000
Commit:     Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
CommitDate: Wed Feb 16 18:58:43 2022 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f560da8a

kde-apps/kcron: Fix CVE-2022-24986

See also: https://kde.org/info/security/advisory-20220216-1.txt

Bug: https://bugs.gentoo.org/833500
Package-Manager: Portage-3.0.30, Repoman-3.0.3
Signed-off-by: Andreas Sturmlechner <asturm <AT> gentoo.org>

 .../kcron/files/kcron-21.12.2-CVE-2022-24986.patch | 291 +++++++++++++++++++++
 .../kcron-21.12.2-KCronHelper-return-error.patch   |  44 ++++
 kde-apps/kcron/kcron-21.12.2-r1.ebuild             |  37 +++
 3 files changed, 372 insertions(+)

diff --git a/kde-apps/kcron/files/kcron-21.12.2-CVE-2022-24986.patch b/kde-apps/kcron/files/kcron-21.12.2-CVE-2022-24986.patch
new file mode 100644
index 000000000000..d64ff31034c4
--- /dev/null
+++ b/kde-apps/kcron/files/kcron-21.12.2-CVE-2022-24986.patch
@@ -0,0 +1,291 @@
+From ef4266e3d5ea741c4d4f442a2cb12a317d7502a1 Mon Sep 17 00:00:00 2001
+From: Albert Astals Cid <aacid@kde.org>
+Date: Tue, 15 Feb 2022 23:32:22 +0100
+Subject: [PATCH] Improve temporary file handling
+
+---
+ src/crontablib/ctSystemCron.cpp | 21 ++-------
+ src/crontablib/ctcron.cpp       | 79 +++++++++++++--------------------
+ src/crontablib/ctcron.h         | 12 ++---
+ src/helper/kcronhelper.cpp      |  5 ++-
+ 4 files changed, 42 insertions(+), 75 deletions(-)
+
+diff --git a/src/crontablib/ctSystemCron.cpp b/src/crontablib/ctSystemCron.cpp
+index 4b17042..e7fc535 100644
+--- a/src/crontablib/ctSystemCron.cpp
++++ b/src/crontablib/ctSystemCron.cpp
+@@ -11,7 +11,7 @@
+ #include <KLocalizedString>
+ #include <KShell>
+ 
+-#include <QTemporaryFile>
++#include <QFileInfo>
+ 
+ #include "cthost.h"
+ #include "cttask.h"
+@@ -28,20 +28,6 @@ CTSystemCron::CTSystemCron(const QString &crontabBinary)
+ 
+     d->crontabBinary = crontabBinary;
+ 
+-    QTemporaryFile tmp;
+-    tmp.open();
+-    d->tmpFileName = tmp.fileName();
+-
+-    CommandLine readCommandLine;
+-
+-    readCommandLine.commandLine = QStringLiteral("cat");
+-    readCommandLine.parameters << QStringLiteral("/etc/crontab");
+-    readCommandLine.standardOutputFile = d->tmpFileName;
+-
+-    d->writeCommandLine.commandLine = QStringLiteral("cat");
+-    d->writeCommandLine.parameters << d->tmpFileName;
+-    d->writeCommandLine.standardOutputFile = QStringLiteral("/etc/crontab");
+-
+     d->userLogin = i18n("root");
+     d->userRealName = d->userLogin;
+ 
+@@ -50,8 +36,9 @@ CTSystemCron::CTSystemCron(const QString &crontabBinary)
+ 
+     // Don't set error if it can't be read, it means the user
+     // doesn't have a crontab.
+-    if (readCommandLine.execute().exitCode == 0) {
+-        this->parseFile(d->tmpFileName);
++    const QString crontabFile = QStringLiteral("/etc/crontab");
++    if (QFileInfo::exists(crontabFile)) {
++        parseFile(crontabFile);
+     }
+ 
+     d->initialTaskCount = d->task.size();
+diff --git a/src/crontablib/ctcron.cpp b/src/crontablib/ctcron.cpp
+index 9d4ef26..b6bd90b 100644
+--- a/src/crontablib/ctcron.cpp
++++ b/src/crontablib/ctcron.cpp
+@@ -35,10 +35,6 @@ CommandLineStatus CommandLine::execute()
+ {
+     QProcess process;
+ 
+-    if (!standardOutputFile.isEmpty()) {
+-        process.setStandardOutputFile(standardOutputFile);
+-    }
+-
+     int exitCode;
+     process.start(commandLine, parameters);
+     if (!process.waitForStarted()) {
+@@ -51,9 +47,6 @@ CommandLineStatus CommandLine::execute()
+     CommandLineStatus commandLineStatus;
+ 
+     commandLineStatus.commandLine = commandLine + QLatin1String(" ") + parameters.join(QLatin1String(" "));
+-    if (!standardOutputFile.isEmpty()) {
+-        commandLineStatus.commandLine += QLatin1String(" > ") + standardOutputFile;
+-    }
+ 
+     commandLineStatus.standardOutput = QLatin1String(process.readAllStandardOutput());
+     commandLineStatus.standardError = QLatin1String(process.readAllStandardError());
+@@ -73,27 +66,15 @@ CTCron::CTCron(const QString &crontabBinary, const struct passwd *userInfos, boo
+ 
+     d->crontabBinary = crontabBinary;
+ 
+-    QTemporaryFile tmp;
+-    tmp.open();
+-    d->tmpFileName = tmp.fileName();
+-
+     CommandLine readCommandLine;
+ 
+     // regular user, so provide user's own crontab
+     if (currentUserCron) {
+         readCommandLine.commandLine = d->crontabBinary;
+         readCommandLine.parameters << QStringLiteral("-l");
+-        readCommandLine.standardOutputFile = d->tmpFileName;
+-
+-        d->writeCommandLine.commandLine = d->crontabBinary;
+-        d->writeCommandLine.parameters << d->tmpFileName;
+     } else {
+         readCommandLine.commandLine = d->crontabBinary;
+         readCommandLine.parameters << QStringLiteral("-u") << QLatin1String(userInfos->pw_name) << QStringLiteral("-l");
+-        readCommandLine.standardOutputFile = d->tmpFileName;
+-
+-        d->writeCommandLine.commandLine = d->crontabBinary;
+-        d->writeCommandLine.parameters << QStringLiteral("-u") << QLatin1String(userInfos->pw_name) << d->tmpFileName;
+     }
+ 
+     d->initialTaskCount = 0;
+@@ -108,7 +89,8 @@ CTCron::CTCron(const QString &crontabBinary, const struct passwd *userInfos, boo
+     // Don't set error if it can't be read, it means the user doesn't have a crontab.
+     CommandLineStatus commandLineStatus = readCommandLine.execute();
+     if (commandLineStatus.exitCode == 0) {
+-        this->parseFile(d->tmpFileName);
++        QTextStream stream(&commandLineStatus.standardOutput);
++        parseTextStream(&stream);
+     } else {
+         qCDebug(KCM_CRON_LOG) << "Error when executing command" << commandLineStatus.commandLine;
+         qCDebug(KCM_CRON_LOG) << "Standard output :" << commandLineStatus.standardOutput;
+@@ -171,12 +153,17 @@ void CTCron::parseFile(const QString &fileName)
+         return;
+     }
+ 
++    QTextStream in(&file);
++    parseTextStream(&in);
++}
++
++void CTCron::parseTextStream(QTextStream *stream)
++{
+     QString comment;
+     bool leadingComment = true;
+ 
+-    QTextStream in(&file);
+-    while (!in.atEnd()) {
+-        QString line = in.readLine();
++    while (!stream->atEnd()) {
++        QString line = stream->readLine();
+ 
+         // search for comments "#" but not disabled tasks "#\"
+         if (line.indexOf(QLatin1String("#")) == 0 && line.indexOf(QLatin1String("\\")) != 1) {
+@@ -257,24 +244,6 @@ CTCron::~CTCron()
+     delete d;
+ }
+ 
+-bool CTCron::saveToFile(const QString &fileName)
+-{
+-    QFile file(fileName);
+-    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+-        return false;
+-    }
+-
+-    // qCDebug(KCM_CRON_LOG) << exportCron();
+-
+-    QTextStream out(&file);
+-    out << exportCron();
+-
+-    out.flush();
+-    file.close();
+-
+-    return true;
+-}
+-
+ CTSaveStatus CTCron::prepareSaveStatusError(const CommandLineStatus &commandLineStatus)
+ {
+     QString standardOutput;
+@@ -307,24 +276,29 @@ CTSaveStatus CTCron::prepareSaveStatusError(const CommandLineStatus &commandLine
+ CTSaveStatus CTCron::save()
+ {
+     // write to temp file
+-    bool saveStatus = saveToFile(d->tmpFileName);
+-    if (!saveStatus) {
+-        return CTSaveStatus(i18n("Unable to open crontab file for writing"), i18n("The file %1 could not be opened.", d->tmpFileName));
++    QTemporaryFile tmp;
++    if (!tmp.open()) {
++        return CTSaveStatus(i18n("Unable to open crontab file for writing"), i18n("The file %1 could not be opened.", tmp.fileName()));
++    }
++
++    {
++        QTextStream out(&tmp);
++        out << exportCron();
++        out.flush();
+     }
++    tmp.close();
+ 
+     // For root permissions.
+     if (d->systemCron) {
+         qCDebug(KCM_CRON_LOG) << "Attempting to save system cron";
+         QVariantMap args;
+-        args.insert(QStringLiteral("source"), d->tmpFileName);
+-        args.insert(QStringLiteral("target"), d->writeCommandLine.standardOutputFile);
++        args.insert(QStringLiteral("source"), tmp.fileName());
+         KAuth::Action saveAction(QStringLiteral("local.kcron.crontab.save"));
+         saveAction.setHelperId(QStringLiteral("local.kcron.crontab"));
+         saveAction.setArguments(args);
+         KAuth::ExecuteJob *job = saveAction.execute();
+         if (!job->exec())
+             qCDebug(KCM_CRON_LOG) << "KAuth returned an error: " << job->error() << job->errorText();
+-        QFile::remove(d->tmpFileName);
+         if (job->error() > 0) {
+             return CTSaveStatus(i18n("KAuth::ExecuteJob Error"), job->errorText());
+         }
+@@ -333,8 +307,15 @@ CTSaveStatus CTCron::save()
+     else {
+         qCDebug(KCM_CRON_LOG) << "Attempting to save user cron";
+         // Save without root permissions.
+-        const CommandLineStatus commandLineStatus = d->writeCommandLine.execute();
+-        QFile::remove(d->tmpFileName);
++        CommandLine writeCommandLine;
++        writeCommandLine.commandLine = d->crontabBinary;
++        if (d->currentUserCron) {
++            writeCommandLine.parameters << tmp.fileName();
++        } else {
++            writeCommandLine.parameters << QStringLiteral("-u") << d->userLogin << tmp.fileName();
++        }
++
++        const CommandLineStatus commandLineStatus = writeCommandLine.execute();
+         if (commandLineStatus.exitCode != 0) {
+             return prepareSaveStatusError(commandLineStatus);
+         }
+diff --git a/src/crontablib/ctcron.h b/src/crontablib/ctcron.h
+index b8d4ac0..f02b136 100644
+--- a/src/crontablib/ctcron.h
++++ b/src/crontablib/ctcron.h
+@@ -16,6 +16,9 @@ class CTTask;
+ class CTVariable;
+ class CTInitializationError;
+ 
++class QFile;
++class QTextStream;
++
+ struct passwd;
+ 
+ #include "ctSaveStatus.h"
+@@ -38,8 +41,6 @@ public:
+ 
+     QStringList parameters;
+ 
+-    QString standardOutputFile;
+-
+     CommandLineStatus execute();
+ };
+ 
+@@ -86,10 +87,6 @@ public:
+     int initialTaskCount;
+     int initialVariableCount;
+ 
+-    CommandLine writeCommandLine;
+-
+-    QString tmpFileName;
+-
+     /**
+      * Contains path to the crontab binary file.
+      */
+@@ -201,8 +198,7 @@ protected:
+      * Parses crontab file format.
+      */
+     void parseFile(const QString &fileName);
+-
+-    bool saveToFile(const QString &fileName);
++    void parseTextStream(QTextStream *stream);
+ 
+     CTSaveStatus prepareSaveStatusError(const CommandLineStatus &commandLineStatus);
+     // d probably stands for data.
+diff --git a/src/helper/kcronhelper.cpp b/src/helper/kcronhelper.cpp
+index d610c00..96fe8a0 100644
+--- a/src/helper/kcronhelper.cpp
++++ b/src/helper/kcronhelper.cpp
+@@ -32,7 +32,7 @@ ActionReply KcronHelper::save(const QVariantMap &args)
+ {
+     qCDebug(KCM_CRON_HELPER_LOG) << "running actions";
+     const QString source = args[QLatin1String("source")].toString();
+-    const QString destination = args[QLatin1String("target")].toString();
++    const QString destination = QStringLiteral("/etc/crontab");
+     {
+         QFile destinationFile(destination);
+         if (destinationFile.exists() && !destinationFile.remove()) {
+@@ -44,6 +44,9 @@ ActionReply KcronHelper::save(const QVariantMap &args)
+     }
+     {
+         QFile sourceFile(source);
++        if (!sourceFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther)) {
++            qCWarning(KCM_CRON_HELPER_LOG) << "can't change permissions to 644";
++        }
+         if (!sourceFile.copy(destination)) {
+             qCWarning(KCM_CRON_HELPER_LOG) << "can't write into the system file" << sourceFile.errorString();
+             ActionReply reply = ActionReply::HelperErrorReply();
+-- 
+GitLab
+

diff --git a/kde-apps/kcron/files/kcron-21.12.2-KCronHelper-return-error.patch b/kde-apps/kcron/files/kcron-21.12.2-KCronHelper-return-error.patch
new file mode 100644
index 000000000000..e63a24dae5c8
--- /dev/null
+++ b/kde-apps/kcron/files/kcron-21.12.2-KCronHelper-return-error.patch
@@ -0,0 +1,44 @@
+From 2c04c9f665283e8480a65f4ac0accfe6a8e0539a Mon Sep 17 00:00:00 2001
+From: Albert Astals Cid <aacid@kde.org>
+Date: Mon, 31 Jan 2022 23:45:12 +0100
+Subject: [PATCH] KCronHelper: Return error when things don't work out
+
+---
+ src/helper/kcronhelper.cpp | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/src/helper/kcronhelper.cpp b/src/helper/kcronhelper.cpp
+index c5d3df2..d610c00 100644
+--- a/src/helper/kcronhelper.cpp
++++ b/src/helper/kcronhelper.cpp
+@@ -33,11 +33,23 @@ ActionReply KcronHelper::save(const QVariantMap &args)
+     qCDebug(KCM_CRON_HELPER_LOG) << "running actions";
+     const QString source = args[QLatin1String("source")].toString();
+     const QString destination = args[QLatin1String("target")].toString();
+-    if (!QFile::remove(destination)) {
+-        qCWarning(KCM_CRON_HELPER_LOG) << "can't remove file, it doesn't exist";
++    {
++        QFile destinationFile(destination);
++        if (destinationFile.exists() && !destinationFile.remove()) {
++            ActionReply reply = ActionReply::HelperErrorReply();
++            qCWarning(KCM_CRON_HELPER_LOG) << "can't remove file" << destinationFile.errorString();
++            reply.setErrorDescription(destinationFile.errorString());
++            return reply;
++        }
+     }
+-    if (!QFile::copy(source, destination)) {
+-        qCWarning(KCM_CRON_HELPER_LOG) << "can't write into the system file, something went wrong";
++    {
++        QFile sourceFile(source);
++        if (!sourceFile.copy(destination)) {
++            qCWarning(KCM_CRON_HELPER_LOG) << "can't write into the system file" << sourceFile.errorString();
++            ActionReply reply = ActionReply::HelperErrorReply();
++            reply.setErrorDescription(sourceFile.errorString());
++            return reply;
++        }
+     }
+     return ActionReply::SuccessReply();
+ }
+-- 
+GitLab
+

diff --git a/kde-apps/kcron/kcron-21.12.2-r1.ebuild b/kde-apps/kcron/kcron-21.12.2-r1.ebuild
new file mode 100644
index 000000000000..7485cadb18ac
--- /dev/null
+++ b/kde-apps/kcron/kcron-21.12.2-r1.ebuild
@@ -0,0 +1,37 @@
+# Copyright 1999-2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+ECM_HANDBOOK="forceoptional"
+KFMIN=5.88.0
+QTMIN=5.15.2
+inherit ecm kde.org
+
+DESCRIPTION="KDE Task Scheduler"
+HOMEPAGE="https://apps.kde.org/kcron/"
+
+LICENSE="GPL-2" # TODO: CHECK
+SLOT="5"
+KEYWORDS="~amd64 ~arm64 ~ppc64 ~riscv ~x86"
+IUSE=""
+
+DEPEND="
+	>=dev-qt/qtgui-${QTMIN}:5
+	>=dev-qt/qtprintsupport-${QTMIN}:5
+	>=dev-qt/qtwidgets-${QTMIN}:5
+	>=kde-frameworks/kauth-${KFMIN}:5
+	>=kde-frameworks/kconfigwidgets-${KFMIN}:5
+	>=kde-frameworks/kcoreaddons-${KFMIN}:5
+	>=kde-frameworks/ki18n-${KFMIN}:5
+	>=kde-frameworks/kio-${KFMIN}:5
+	>=kde-frameworks/kwidgetsaddons-${KFMIN}:5
+"
+RDEPEND="${DEPEND}
+	virtual/cron
+"
+
+PATCHES=(
+	"${FILESDIR}"/${P}-KCronHelper-return-error.patch
+	"${FILESDIR}"/${P}-CVE-2022-24986.patch
+)


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2022-02-16 18:59 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-16 18:58 [gentoo-commits] repo/gentoo:master commit in: kde-apps/kcron/files/, kde-apps/kcron/ Andreas Sturmlechner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox