Compare commits

...

6 Commits

Author SHA1 Message Date
Andrius Štikonas 4ef17463ff Make sure that path passed to WriteData is block device. 2022-02-05 14:42:17 +00:00
Andrius Štikonas 81a5eae665 Restrict CopyFileData to writing to already existing files. 2022-02-05 14:12:38 +00:00
Andrius Štikonas 3903ae1b83 Rename CopyBlocks to CopyFileData. 2022-02-05 14:05:50 +00:00
Andrius Štikonas 949ce01ae4 Check for relative paths in ExternalCommandHelper::CopyBlocks. 2022-02-05 13:48:37 +00:00
Andrius Štikonas 5d1c03b9d8 Restrict QProcess::ProcessChannelMode to two used values.
Casting and passing the processChannel argument unfiltered to QProcess
could pose a security issue if future additions are made to
QProcess that introduce new behaviour.
2022-02-05 13:24:38 +00:00
Andrius Štikonas 1502494eda Be a bit more strict in root helper when checking path to /etc/fstab. 2022-02-05 13:13:12 +00:00
3 changed files with 31 additions and 6 deletions

View File

@ -160,7 +160,7 @@ bool ExternalCommand::copyBlocks(const CopySource& source, CopyTarget& target)
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::progress, this, &ExternalCommand::progress); connect(interface, &OrgKdeKpmcoreExternalcommandInterface::progress, this, &ExternalCommand::progress);
connect(interface, &OrgKdeKpmcoreExternalcommandInterface::report, this, &ExternalCommand::reportSignal); connect(interface, &OrgKdeKpmcoreExternalcommandInterface::report, this, &ExternalCommand::reportSignal);
QDBusPendingCall pcall = interface->CopyBlocks(source.path(), source.firstByte(), source.length(), QDBusPendingCall pcall = interface->CopyFileData(source.path(), source.firstByte(), source.length(),
target.path(), target.firstByte(), blockSize); target.path(), target.firstByte(), blockSize);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);

View File

@ -136,7 +136,7 @@ bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray
return false; return false;
} }
// Do not allow using this helper for writing to arbitrary location // Do not allow using this helper for writing to arbitrary location
if ( !filePath.contains(QStringLiteral("/etc/fstab")) ) if ( filePath != QStringLiteral("/etc/fstab") )
return false; return false;
QFile device(filePath); QFile device(filePath);
@ -156,7 +156,7 @@ bool ExternalCommandHelper::CreateFile(const QString &filePath, const QByteArray
} }
// If targetDevice is empty then return QByteArray with data that was read from disk. // If targetDevice is empty then return QByteArray with data that was read from disk.
QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength, const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize) QVariantMap ExternalCommandHelper::CopyFileData(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength, const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize)
{ {
if (!isCallerAuthorized()) { if (!isCallerAuthorized()) {
return {}; return {};
@ -172,6 +172,18 @@ QVariantMap ExternalCommandHelper::CopyBlocks(const QString& sourceDevice, const
return {}; return {};
} }
// Check for relative paths
std::filesystem::path sourcePath(sourceDevice.toStdU16String());
std::filesystem::path targetPath(targetDevice.toStdU16String());
if(sourcePath.is_relative() || targetPath.is_relative()) {
return {};
}
// Only allow writing to existing files.
if(!std::filesystem::exists(targetPath)) {
return {};
}
QVariantMap reply; QVariantMap reply;
reply[QStringLiteral("success")] = true; reply[QStringLiteral("success")] = true;
@ -279,7 +291,7 @@ QByteArray ExternalCommandHelper::ReadData(const QString& device, const qint64 o
if (length > MiB) { if (length > MiB) {
return {}; return {};
} }
if (!std::filesystem::is_block_file(device.toStdString())) { if (!std::filesystem::is_block_file(device.toStdU16String())) {
qWarning() << "Not a block device"; qWarning() << "Not a block device";
return {}; return {};
} }
@ -301,7 +313,15 @@ bool ExternalCommandHelper::WriteData(const QByteArray& buffer, const QString& t
if ( targetDevice.left(5) != QStringLiteral("/dev/") ) if ( targetDevice.left(5) != QStringLiteral("/dev/") )
return false; return false;
return writeData(targetDevice, buffer, targetOffset); auto targetPath = std::filesystem::path(targetDevice.toStdU16String());
if (!std::filesystem::is_block_file(targetDevice.toStdU16String())) {
qWarning() << "Not a block device";
return {};
}
auto canonicalTargetPath = std::filesystem::canonical(targetPath);
return writeData(QLatin1String(canonicalTargetPath.c_str()), buffer, targetOffset);
} }
QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode) QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
@ -334,6 +354,11 @@ QVariantMap ExternalCommandHelper::RunCommand(const QString& command, const QStr
QProcess cmd; QProcess cmd;
cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } ); cmd.setEnvironment( { QStringLiteral("LVM_SUPPRESS_FD_WARNINGS=1") } );
if((processChannelMode != QProcess::SeparateChannels) && (processChannelMode != QProcess::MergedChannels)) {
reply[QStringLiteral("success")] = false;
return reply;
}
cmd.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannelMode)); cmd.setProcessChannelMode(static_cast<QProcess::ProcessChannelMode>(processChannelMode));
cmd.start(command, arguments); cmd.start(command, arguments);
cmd.write(input); cmd.write(input);

View File

@ -38,7 +38,7 @@ public:
public Q_SLOTS: public Q_SLOTS:
Q_SCRIPTABLE QVariantMap RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode); Q_SCRIPTABLE QVariantMap RunCommand(const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
Q_SCRIPTABLE QVariantMap CopyBlocks(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength, Q_SCRIPTABLE QVariantMap CopyFileData(const QString& sourceDevice, const qint64 sourceOffset, const qint64 sourceLength,
const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize); const QString& targetDevice, const qint64 targetOffset, const qint64 blockSize);
Q_SCRIPTABLE QByteArray ReadData(const QString& device, const qint64 offset, const qint64 length); Q_SCRIPTABLE QByteArray ReadData(const QString& device, const qint64 offset, const qint64 length);
Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset); Q_SCRIPTABLE bool WriteData(const QByteArray& buffer, const QString& targetDevice, const qint64 targetOffset);