Do not use external process dd.

BUG: 398154
This commit is contained in:
Andrius Štikonas 2018-11-25 20:50:22 +00:00
parent 0e4fca8de6
commit 09e4d47e07
8 changed files with 90 additions and 18 deletions

View File

@ -157,7 +157,7 @@ bool fat12::create(Report& report, const QString& deviceNode)
bool fat12::updateUUID(Report& report, const QString& deviceNode) const
{
qint64 t = time(nullptr);
long int t = time(nullptr);
char uuid[4];
for (auto &u : uuid) {
@ -165,9 +165,7 @@ bool fat12::updateUUID(Report& report, const QString& deviceNode) const
t >>= 8;
}
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=39") });
cmd.write(QByteArray(uuid, sizeof(uuid)));
return cmd.start();
ExternalCommand cmd;
return cmd.writeData(report, QByteArray(uuid, sizeof(uuid)), deviceNode, 39);
}
}

View File

@ -14,6 +14,7 @@
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>.*
*************************************************************************/
#include "fs/fat32.h"
#include "util/externalcommand.h"
@ -48,7 +49,8 @@ bool fat32::create(Report& report, const QString& deviceNode)
bool fat32::updateUUID(Report& report, const QString& deviceNode) const
{
qint64 t = time(nullptr);
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2)
long int t = time(nullptr);
char uuid[4];
for (auto &u : uuid) {
@ -56,10 +58,7 @@ bool fat32::updateUUID(Report& report, const QString& deviceNode) const
t >>= 8;
}
// HACK: replace this hack with fatlabel "-i" (dosfstools 4.2)
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode, QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=67") });
cmd.write(QByteArray(uuid, sizeof(uuid)));
return cmd.start();
ExternalCommand cmd;
return cmd.writeData(report, QByteArray(uuid, sizeof(uuid)), deviceNode, 67);
}
}

View File

@ -29,7 +29,6 @@
#include <QString>
#include <QStringList>
#include <QFile>
#include <QUuid>
#include <algorithm>
#include <ctime>
@ -188,10 +187,8 @@ bool ntfs::updateBootSector(Report& report, const QString& deviceNode) const
std::swap(s[1], s[2]);
#endif
ExternalCommand cmd(report, QStringLiteral("dd"), { QStringLiteral("of=") + deviceNode , QStringLiteral("bs=1"), QStringLiteral("count=4"), QStringLiteral("seek=28") });
cmd.write(QByteArray(s, sizeof(s)));
if (!cmd.start()) {
ExternalCommand cmd;
if (!cmd.writeData(report, QByteArray(s, sizeof(s)), deviceNode, 28)) {
Log() << xi18nc("@info:progress", "Could not write new start sector to partition <filename>%1</filename> when trying to update the NTFS boot sector.", deviceNode);
return false;
}

View File

@ -241,6 +241,55 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target)
return rval;
}
bool ExternalCommand::writeData(Report& commandReport, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte)
{
d->m_Report = commandReport.newChild();
if (report())
report()->setCommand(xi18nc("@info:status", "Command: %1 %2", command(), args().join(QStringLiteral(" "))));
bool rval = true;
if (!QDBusConnection::systemBus().isConnected()) {
qWarning() << "Could not connect to DBus system bus";
return false;
}
auto *interface = new org::kde::kpmcore::externalcommand(QStringLiteral("org.kde.kpmcore.externalcommand"),
QStringLiteral("/Helper"), QDBusConnection::systemBus(), this);
interface->setTimeout(10 * 24 * 3600 * 1000); // 10 days
QByteArray request;
const quint64 nonce = interface->getNonce();
request.setNum(nonce);
request.append(buffer);
request.append(deviceNode.toUtf8());
request.append(QByteArray::number(firstByte));
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512);
QDBusPendingCall pcall = interface->writeData(privateKey->signMessage(hash, QCA::EMSA3_Raw), nonce,
buffer, deviceNode, firstByte);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
QEventLoop loop;
auto exitLoop = [&] (QDBusPendingCallWatcher *watcher) {
loop.exit();
if (watcher->isError())
qWarning() << watcher->error();
else {
QDBusPendingReply<bool> reply = *watcher;
rval = reply.argumentAt<0>();
}
setExitCode(!rval);
};
connect(watcher, &QDBusPendingCallWatcher::finished, exitLoop);
loop.exec();
return rval;
}
bool ExternalCommand::write(const QByteArray& input)
{

View File

@ -69,6 +69,7 @@ public:
public:
bool copyBlocks(CopySource& source, CopyTarget& target);
bool writeData(Report& report, const QByteArray& buffer, const QString& deviceNode, const quint64 firstByte); // same as copyBlocks but from QByteArray
/**< @param cmd the command to run */
void setCommand(const QString& cmd);

View File

@ -21,7 +21,6 @@
QString allowedCommands[] = {
// TODO try to remove these later
QStringLiteral("mv"),
QStringLiteral("dd"),
// TODO no root needed
QStringLiteral("lsblk"),

View File

@ -152,6 +152,7 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
return true;
}
// If targetDevice is empty then return QByteArray with data that was read from disk.
QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const quint64 nonce, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize)
{
QVariantMap reply;
@ -213,7 +214,7 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const
bool rval = true;
while (blocksCopied < blocksToCopy) {
while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) {
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
break;
@ -265,6 +266,33 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const
return reply;
}
bool ExternalCommandHelper::writeData(const QByteArray& signature, const quint64 nonce, const QByteArray buffer, const QString& targetDevice, const qint64 targetFirstByte)
{
if (m_Nonces.find(nonce) != m_Nonces.end())
m_Nonces.erase( nonce );
else
return false;
QByteArray request;
request.setNum(nonce);
request.append(buffer);
request.append(targetDevice.toUtf8());
request.append(QByteArray::number(targetFirstByte));
// Do not allow using this helper for writing to arbitrary location
if ( targetDevice.left(5) != QStringLiteral("/dev/") && !targetDevice.contains(QStringLiteral("/etc/fstab")))
return false;
QByteArray hash = QCryptographicHash::hash(request, QCryptographicHash::Sha512);
if (!m_publicKey.verifyMessage(hash, signature, QCA::EMSA3_Raw)) {
qCritical() << xi18n("Invalid cryptographic signature");
return false;
}
return writeData(targetDevice, buffer, targetFirstByte);
}
QVariantMap ExternalCommandHelper::start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode)
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

View File

@ -50,6 +50,7 @@ public Q_SLOTS:
Q_SCRIPTABLE quint64 getNonce();
Q_SCRIPTABLE QVariantMap start(const QByteArray& signature, const quint64 nonce, const QString& command, const QStringList& arguments, const QByteArray& input, const int processChannelMode);
Q_SCRIPTABLE QVariantMap copyblocks(const QByteArray& signature, const quint64 nonce, const QString& sourceDevice, const qint64 sourceFirstByte, const qint64 sourceLength, const QString& targetDevice, const qint64 targetFirstByte, const qint64 blockSize);
Q_SCRIPTABLE bool writeData(const QByteArray& signature, const quint64 nonce, const QByteArray buffer, const QString& targetDevice, const qint64 targetFirstByte);
Q_SCRIPTABLE void exit(const QByteArray& signature, const quint64 nonce);
private: