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

View File

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

View File

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

View File

@ -241,6 +241,55 @@ bool ExternalCommand::copyBlocks(CopySource& source, CopyTarget& target)
return rval; 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) bool ExternalCommand::write(const QByteArray& input)
{ {

View File

@ -69,6 +69,7 @@ public:
public: public:
bool copyBlocks(CopySource& source, CopyTarget& target); 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 */ /**< @param cmd the command to run */
void setCommand(const QString& cmd); void setCommand(const QString& cmd);

View File

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

View File

@ -152,6 +152,7 @@ bool ExternalCommandHelper::writeData(const QString &targetDevice, const QByteAr
return true; 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 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; QVariantMap reply;
@ -213,7 +214,7 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const
bool rval = true; bool rval = true;
while (blocksCopied < blocksToCopy) { while (blocksCopied < blocksToCopy && !targetDevice.isEmpty()) {
if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize))) if (!(rval = readData(sourceDevice, buffer, readOffset + blockSize * blocksCopied * copyDirection, blockSize)))
break; break;
@ -265,6 +266,33 @@ QVariantMap ExternalCommandHelper::copyblocks(const QByteArray& signature, const
return reply; 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) 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")); QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

View File

@ -50,6 +50,7 @@ public Q_SLOTS:
Q_SCRIPTABLE quint64 getNonce(); 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 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 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); Q_SCRIPTABLE void exit(const QByteArray& signature, const quint64 nonce);
private: private: