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()))
|
if (!( openCmd.start(-1) && openCmd.write(m_passphrase.toLocal8Bit() + '\n') == m_passphrase.toLocal8Bit().length() + 1 && openCmd.waitFor()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
setPayloadSize();
|
||||||
scan(deviceNode);
|
scan(deviceNode);
|
||||||
|
|
||||||
if (mapperName().isEmpty())
|
if (mapperName().isEmpty())
|
||||||
|
@ -259,6 +260,7 @@ bool luks::cryptOpen(QWidget* parent, const QString& deviceNode)
|
||||||
QString passphrase = dlg.password();
|
QString passphrase = dlg.password();
|
||||||
ExternalCommand openCmd(QStringLiteral("cryptsetup"),
|
ExternalCommand openCmd(QStringLiteral("cryptsetup"),
|
||||||
{ QStringLiteral("open"),
|
{ QStringLiteral("open"),
|
||||||
|
QStringLiteral("--tries"), QStringLiteral("1"),
|
||||||
deviceNode,
|
deviceNode,
|
||||||
suggestedMapperName(deviceNode) });
|
suggestedMapperName(deviceNode) });
|
||||||
|
|
||||||
|
@ -490,19 +492,18 @@ bool luks::resize(Report& report, const QString& deviceNode, qint64 newLength) c
|
||||||
if (mapperName().isEmpty())
|
if (mapperName().isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
qint64 payloadLength = newLength - payloadOffset();
|
|
||||||
if ( newLength - length() * sectorSize() > 0 )
|
if ( newLength - length() * sectorSize() > 0 )
|
||||||
{
|
{
|
||||||
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
|
ExternalCommand cryptResizeCmd(report, QStringLiteral("cryptsetup"), { QStringLiteral("resize"), mapperName() });
|
||||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||||
|
|
||||||
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
|
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"),
|
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() });
|
QStringLiteral("resize"), mapperName() });
|
||||||
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
report.line() << xi18nc("@info:progress", "Resizing LUKS crypt on partition <filename>%1</filename>.", deviceNode);
|
||||||
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
|
if (cryptResizeCmd.run(-1) && cryptResizeCmd.exitCode() == 0)
|
||||||
|
@ -589,8 +590,7 @@ void luks::getMapperName(const QString& deviceNode)
|
||||||
|
|
||||||
void luks::getLuksInfo(const QString& deviceNode)
|
void luks::getLuksInfo(const QString& deviceNode)
|
||||||
{
|
{
|
||||||
ExternalCommand cmd(QStringLiteral("cryptsetup"),
|
ExternalCommand cmd(QStringLiteral("cryptsetup"), { QStringLiteral("luksDump"), deviceNode });
|
||||||
{ QStringLiteral("luksDump"), deviceNode });
|
|
||||||
if (cmd.run(-1) && cmd.exitCode() == 0) {
|
if (cmd.run(-1) && cmd.exitCode() == 0) {
|
||||||
QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)"));
|
QRegularExpression re(QStringLiteral("Cipher name:\\s+(\\w+)"));
|
||||||
QRegularExpressionMatch rem = re.match(cmd.output());
|
QRegularExpressionMatch rem = re.match(cmd.output());
|
||||||
|
@ -667,6 +667,7 @@ bool luks::canEncryptType(FileSystem::Type type)
|
||||||
|
|
||||||
void luks::initLUKS()
|
void luks::initLUKS()
|
||||||
{
|
{
|
||||||
|
setPayloadSize();
|
||||||
QString mapperNode = mapperName();
|
QString mapperNode = mapperName();
|
||||||
bool isCryptOpen = !mapperNode.isEmpty();
|
bool isCryptOpen = !mapperNode.isEmpty();
|
||||||
setCryptOpen(isCryptOpen);
|
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(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label, FileSystem::Type t = FileSystem::Luks);
|
||||||
~luks() override;
|
~luks() override;
|
||||||
|
|
||||||
|
enum KeyLocation {
|
||||||
|
unknown,
|
||||||
|
dmcrypt,
|
||||||
|
keyring
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init() override;
|
void init() override;
|
||||||
void scan(const QString& deviceNode) override;
|
void scan(const QString& deviceNode) override;
|
||||||
|
@ -167,9 +173,9 @@ public:
|
||||||
QString suggestedMapperName(const QString& deviceNode) const;
|
QString suggestedMapperName(const QString& deviceNode) const;
|
||||||
|
|
||||||
void getMapperName(const QString& deviceNode);
|
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 outerUuid() const;
|
||||||
|
|
||||||
QString mapperName() const { return m_MapperName; }
|
QString mapperName() const { return m_MapperName; }
|
||||||
|
@ -182,8 +188,12 @@ public:
|
||||||
static bool canEncryptType(FileSystem::Type type);
|
static bool canEncryptType(FileSystem::Type type);
|
||||||
void initLUKS();
|
void initLUKS();
|
||||||
|
|
||||||
|
virtual luks::KeyLocation keyLocation() { return luks::dmcrypt; };
|
||||||
|
bool testPassphrase(const QString& deviceNode, const QString& passphrase) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString readOuterUUID(const QString& deviceNode) const;
|
virtual QString readOuterUUID(const QString& deviceNode) const;
|
||||||
|
void setPayloadSize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CommandSupportType m_GetUsed;
|
static CommandSupportType m_GetUsed;
|
||||||
|
@ -213,7 +223,10 @@ protected:
|
||||||
QString m_HashName;
|
QString m_HashName;
|
||||||
qint64 m_KeySize;
|
qint64 m_KeySize;
|
||||||
qint64 m_PayloadOffset;
|
qint64 m_PayloadOffset;
|
||||||
|
qint64 m_PayloadSize;
|
||||||
QString m_outerUuid;
|
QString m_outerUuid;
|
||||||
|
|
||||||
|
luks::KeyLocation m_KeyLocation = unknown;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
|
|
||||||
#include "fs/luks2.h"
|
#include "fs/luks2.h"
|
||||||
|
|
||||||
|
#include "util/externalcommand.h"
|
||||||
|
#include "util/report.h"
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include <KLocalizedString>
|
||||||
|
|
||||||
namespace FS
|
namespace FS
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -36,4 +43,64 @@ FileSystem::Type luks2::type() const
|
||||||
return FileSystem::Luks2;
|
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(qint64 firstsector, qint64 lastsector, qint64 sectorsused, const QString& label);
|
||||||
~luks2() override;
|
~luks2() override;
|
||||||
|
|
||||||
|
bool resize(Report& report, const QString& deviceNode, qint64 length) const override;
|
||||||
|
|
||||||
FileSystem::Type type() const override;
|
FileSystem::Type type() const override;
|
||||||
|
|
||||||
|
luks::KeyLocation keyLocation() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,6 @@ bool SetPartGeometryJob::run(Report& parent)
|
||||||
delete backendPartitionTable;
|
delete backendPartitionTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
delete backendDevice;
|
delete backendDevice;
|
||||||
} else
|
} 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());
|
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