Initial support for resizing LUKS2 volumes.
Does not yet work when LUKS2 is used with dm-integrity.
This commit is contained in:
parent
78a9ede36c
commit
4773f49edc
|
@ -143,6 +143,7 @@ bool luks::create(Report& report, const QString& deviceNode)
|
|||
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
|
||||
return false;
|
||||
|
||||
setPayloadSize();
|
||||
scan(deviceNode);
|
||||
|
||||
if (mapperName().isEmpty())
|
||||
|
@ -259,6 +260,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
|
|||
QString passphrase = dlg.password();
|
||||
ExternalCommand openCmd(QStringLiteral("cryptsetup"),
|
||||
{ QStringLiteral("open"),
|
||||
QStringLiteral("--tries"), QStringLiteral("1"),
|
||||
deviceNode,
|
||||
suggestedMapperName(deviceNode) });
|
||||
|
||||
|
@ -490,19 +492,18 @@ bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) c
|
|||
if (mapperName().isEmpty())
|
||||
return false;
|
||||
|
||||
qint64 payloadLength = newLength - payloadOffset();
|
||||
if ( newLength - length() * sectorSize() > 0 )
|
||||
{
|
||||
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
|
||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||
|
||||
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
|
||||
return m_innerFs->resize(report, mapperName(), payloadLength);
|
||||
return m_innerFs->resize(report, mapperName(), m_PayloadSize);
|
||||
}
|
||||
else if (m_innerFs->resize(report, mapperName(), payloadLength))
|
||||
else if (m_innerFs->resize(report, mapperName(), m_PayloadSize))
|
||||
{
|
||||
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"),
|
||||
{ QStringLiteral("--size"), QString::number(payloadLength / 512), // LUKS payload length is specified in multiples of 512 bytes
|
||||
{ QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // LUKS1 payload length is specified in multiples of 512 bytes
|
||||
QStringLiteral("resize"), mapperName() });
|
||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
|
||||
|
@ -589,8 +590,7 @@ void luks::getMapperName(const QString& deviceNode)
|
|||
|
||||
void luks::getLuksInfo(const QString& deviceNode)
|
||||
{
|
||||
ExternalCommand cmd(QStringLiteral("cryptsetup"),
|
||||
{ QStringLiteral("luksDump"), deviceNode });
|
||||
ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode });
|
||||
if (cmd.run(-1) && cmd.exitCode() == 0) {
|
||||
QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)"));
|
||||
QRegularExpressionMatch rem = re.match(cmd.output());
|
||||
|
@ -667,6 +667,7 @@ bool luks::canEncryptType(FileSystem::Type type)
|
|||
|
||||
void luks::initLUKS()
|
||||
{
|
||||
setPayloadSize();
|
||||
QString mapperNode = mapperName();
|
||||
bool isCryptOpen = !mapperNode.isEmpty();
|
||||
setCryptOpen(isCryptOpen);
|
||||
|
@ -676,4 +677,22 @@ void luks::initLUKS()
|
|||
}
|
||||
}
|
||||
|
||||
void luks::setPayloadSize()
|
||||
{
|
||||
ExternalCommand dmsetupCmd(QStringLiteral("dmsetup"), { QStringLiteral("table"), mapperName() });
|
||||
dmsetupCmd.run();
|
||||
QRegularExpression re(QStringLiteral("\\d+ (\\d+)"));
|
||||
QRegularExpressionMatch rem = re.match(dmsetupCmd.output());
|
||||
if (rem.hasMatch())
|
||||
m_PayloadSize = rem.captured(1).toLongLong() * sectorSize();
|
||||
}
|
||||
|
||||
bool luks::testPassphrase(const QString& deviceNode, const QString& passphrase) const {
|
||||
ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("open"), QStringLiteral("--tries"), QStringLiteral("1"), QStringLiteral("--test-passphrase"), deviceNode });
|
||||
if (cmd.start(-1) && cmd.write(passphrase.toLocal8Bit() + '\n') == passphrase.toLocal8Bit().length() + 1 && cmd.waitFor() && cmd.exitCode() == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,6 +43,12 @@ public:
|
|||
luks(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Luks);
|
||||
~luks() override;
|
||||
|
||||
enum KeyLocation {
|
||||
unknown,
|
||||
dmcrypt,
|
||||
keyring
|
||||
};
|
||||
|
||||
public:
|
||||
void init() override;
|
||||
void scan(const QString& deviceNode) override;
|
||||
|
@ -167,9 +173,9 @@ public:
|
|||
QString suggestedMapperName(const QString& deviceNode) const;
|
||||
|
||||
void getMapperName(const QString& deviceNode);
|
||||
void getLuksInfo(const QString& deviceNode);
|
||||
virtual void getLuksInfo(const QString& deviceNode);
|
||||
|
||||
FileSystem* innerFS() const { return m_innerFs; } // avoid calling this unless necessary
|
||||
FileSystem* innerFS() const { return m_innerFs; }
|
||||
QString outerUuid() const;
|
||||
|
||||
QString mapperName() const { return m_MapperName; }
|
||||
|
@ -182,8 +188,12 @@ public:
|
|||
static bool canEncryptType(FileSystem::Type type);
|
||||
void initLUKS();
|
||||
|
||||
virtual luks::KeyLocation keyLocation() { return luks::dmcrypt; };
|
||||
bool testPassphrase(const QString& deviceNode, const QString& passphrase) const;
|
||||
|
||||
protected:
|
||||
virtual QString readOuterUUID(const QString& deviceNode) const;
|
||||
void setPayloadSize();
|
||||
|
||||
public:
|
||||
static CommandSupportType m_GetUsed;
|
||||
|
@ -213,7 +223,10 @@ protected:
|
|||
QString m_HashName;
|
||||
qint64 m_KeySize;
|
||||
qint64 m_PayloadOffset;
|
||||
qint64 m_PayloadSize;
|
||||
QString m_outerUuid;
|
||||
|
||||
luks::KeyLocation m_KeyLocation = unknown;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
|
||||
#include "fs/luks2.h"
|
||||
|
||||
#include "util/externalcommand.h"
|
||||
#include "util/report.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
namespace FS
|
||||
{
|
||||
|
||||
|
@ -36,4 +43,64 @@ FileSystem::Type luks2::type() const
|
|||
return FileSystem::Luks2;
|
||||
}
|
||||
|
||||
bool luks2::resize(Report& report, const QString& deviceNode, qint64 newLength) const
|
||||
{
|
||||
Q_ASSERT(m_innerFs);
|
||||
|
||||
if (mapperName().isEmpty())
|
||||
return false;
|
||||
|
||||
if ( newLength - length() * sectorSize() > 0 )
|
||||
{
|
||||
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
|
||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||
|
||||
cryptResizeCmd.start(-1);
|
||||
if (m_KeyLocation == keyring) {
|
||||
if (m_passphrase.isEmpty())
|
||||
return false;
|
||||
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
|
||||
}
|
||||
cryptResizeCmd.waitFor();
|
||||
if ( cryptResizeCmd.exitCode() == 0 )
|
||||
return m_innerFs->resize(report, mapperName(), m_PayloadSize);
|
||||
}
|
||||
else if (m_innerFs->resize(report, mapperName(), m_PayloadSize))
|
||||
{
|
||||
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"),
|
||||
{ QStringLiteral("--size"), QString::number(m_PayloadSize / 512), // FIXME, LUKS2 can have different sector sizes
|
||||
QStringLiteral("resize"), mapperName() });
|
||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||
cryptResizeCmd.start(-1);
|
||||
if (m_KeyLocation == keyring) {
|
||||
if (m_passphrase.isEmpty())
|
||||
return false;
|
||||
cryptResizeCmd.write(m_passphrase.toLocal8Bit() + '\n');
|
||||
}
|
||||
cryptResizeCmd.waitFor();
|
||||
if ( cryptResizeCmd.exitCode() == 0 )
|
||||
return true;
|
||||
}
|
||||
report.line() << xi18nc("@info:progress", "Resizing encrypted file system on partition <filename>%1</filename> failed.", deviceNode);
|
||||
return false;
|
||||
}
|
||||
|
||||
luks::KeyLocation luks2::keyLocation()
|
||||
{
|
||||
m_KeyLocation = unknown;
|
||||
ExternalCommand statusCmd(QStringLiteral("cryptsetup"), { QStringLiteral("status"), mapperName() });
|
||||
if (statusCmd.run(-1) && statusCmd.exitCode() == 0) {
|
||||
QRegularExpression re(QStringLiteral("key location:\\s+(\\w+)"));
|
||||
QRegularExpressionMatch rem = re.match(statusCmd.output());
|
||||
if (rem.hasMatch()) {
|
||||
if (rem.captured(1) == QStringLiteral("keyring"))
|
||||
m_KeyLocation = keyring;
|
||||
else if (rem.captured(1) == QStringLiteral("dm-crypt"))
|
||||
m_KeyLocation = dmcrypt;
|
||||
}
|
||||
}
|
||||
|
||||
return m_KeyLocation;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,11 @@ public:
|
|||
luks2(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label);
|
||||
~luks2() override;
|
||||
|
||||
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
|
||||
|
||||
FileSystem::Type type() const override;
|
||||
|
||||
luks::KeyLocation keyLocation() override;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@ bool SetPartGeometryJob::run(Report& parent)
|
|||
delete backendPartitionTable;
|
||||
}
|
||||
|
||||
|
||||
delete backendDevice;
|
||||
} else
|
||||
report->line() << xi18nc("@info:progress", "Could not open device <filename>%1</filename> while trying to resize/move partition <filename>%2</filename>.", device().deviceNode(), partition().deviceNode());
|
||||
|
|
Loading…
Reference in New Issue