Merge branch 'issue-1593' into calamares

FIXES #1593
This commit is contained in:
Adriaan de Groot 2021-11-16 15:33:42 +01:00
commit 13cb84aa75
6 changed files with 87 additions and 20 deletions

View File

@ -17,6 +17,10 @@ This release contains contributions from (alphabetically by first name):
- The translation for Sinhala (`si`) has reached 100%. Thank you to - The translation for Sinhala (`si`) has reached 100%. Thank you to
හෙළබස and Sandaruwan, translators for Sinhala, for special effort හෙළබස and Sandaruwan, translators for Sinhala, for special effort
in completing that translation. in completing that translation.
- Logging now supports Redacted names. This reduces the scope for
leaking names or other private information through the logs
(if they are posted to a pastebin). A name is redacted consistently
within one run of Calamares, but differently each time.
## Modules ## ## Modules ##
- *displaymanager* supports the *greetd* display manager, which is a - *displaymanager* supports the *greetd* display manager, which is a
@ -31,6 +35,8 @@ This release contains contributions from (alphabetically by first name):
option, since the kernel automatically picks the right value, while option, since the kernel automatically picks the right value, while
setting it to the wrong one may prevent the system from booting. setting it to the wrong one may prevent the system from booting.
(Thanks Evan) (Thanks Evan)
- The *partition* module no longer logs recognizable disk names or
UUIDs. These are redacted in the logs. #1593
# 3.2.46 (2021-11-09) # # 3.2.46 (2021-11-09) #

View File

@ -20,6 +20,8 @@
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QMutex> #include <QMutex>
#include <QRandomGenerator>
#include <QTextStream>
#include <QTime> #include <QTime>
#include <QVariant> #include <QVariant>
@ -229,7 +231,7 @@ toString( const QVariant& v )
} }
QDebug& QDebug&
operator<<( QDebug& s, const Redacted& l ) operator<<( QDebug& s, const RedactedCommand& l )
{ {
// Special case logging: don't log the (encrypted) password. // Special case logging: don't log the (encrypted) password.
if ( l.list.contains( "usermod" ) ) if ( l.list.contains( "usermod" ) )
@ -252,4 +254,33 @@ operator<<( QDebug& s, const Redacted& l )
return s; return s;
} }
/** @brief Returns a stable-but-private hash of @p context and @p s
*
* Identical strings with the same context will be hashed the same,
* so that they can be logged and still recognized as the-same.
*/
static uint insertRedactedName( const QString& context, const QString& s )
{
static uint salt = QRandomGenerator::global()->generate(); // Just once
uint val = qHash(context, salt);
return qHash(s, val);
}
RedactedName::RedactedName( const QString& context, const QString& s )
: m_id( insertRedactedName(context, s) ),
m_context(context)
{
}
RedactedName::RedactedName(const char *context, const QString& s )
: RedactedName( QString::fromLatin1( context ), s )
{
}
RedactedName::operator QString() const
{
return QString( m_context + '$' + QString::number( m_id, 16 ) );
}
} // namespace Logger } // namespace Logger

View File

@ -145,8 +145,8 @@ public:
{ {
} }
const T& first; const T first;
const U& second; const U second;
}; };
/** /**
@ -214,9 +214,9 @@ public:
* since the log may get posted to bug reports, or stored in * since the log may get posted to bug reports, or stored in
* the target system. * the target system.
*/ */
struct Redacted struct RedactedCommand
{ {
Redacted( const QStringList& l ) RedactedCommand( const QStringList& l )
: list( l ) : list( l )
{ {
} }
@ -224,7 +224,30 @@ struct Redacted
const QStringList& list; const QStringList& list;
}; };
QDebug& operator<<( QDebug& s, const Redacted& l ); QDebug& operator<<( QDebug& s, const RedactedCommand& l );
/** @brief When logging "private" identifiers, keep them consistent but private
*
* Send a string to a logger in such a way that each time it is logged,
* it logs the same way, but without revealing the actual contents.
* This can be applied to user names, UUIDs, etc.
*/
struct RedactedName
{
RedactedName( const char* context, const QString& s );
RedactedName( const QString& context, const QString& s );
operator QString() const;
private:
const uint m_id;
const QString m_context;
};
inline QDebug& operator<<( QDebug& s, const RedactedName& n )
{
return s << NoQuote << QString( n ) << Quote;
}
/** /**
* @brief Formatted logging of a pointer * @brief Formatted logging of a pointer

View File

@ -163,7 +163,7 @@ Calamares::Utils::Runner::run()
} ); } );
} }
cDebug() << Logger::SubEntry << "Running" << Logger::Redacted( m_command ); cDebug() << Logger::SubEntry << "Running" << Logger::RedactedCommand( m_command );
process.start(); process.start();
if ( !process.waitForStarted() ) if ( !process.waitForStarted() )
{ {
@ -225,13 +225,13 @@ Calamares::Utils::Runner::run()
{ {
if ( !output.isEmpty() ) if ( !output.isEmpty() )
{ {
cDebug() << Logger::SubEntry << "Target cmd:" << Logger::Redacted( m_command ) << "Exit code:" << r cDebug() << Logger::SubEntry << "Target cmd:" << Logger::RedactedCommand( m_command ) << "Exit code:" << r
<< "output:\n" << "output:\n"
<< Logger::NoQuote << output; << Logger::NoQuote << output;
} }
else else
{ {
cDebug() << Logger::SubEntry << "Target cmd:" << Logger::Redacted( m_command ) << "Exit code:" << r cDebug() << Logger::SubEntry << "Target cmd:" << Logger::RedactedCommand( m_command ) << "Exit code:" << r
<< "(no output)"; << "(no output)";
} }
} }

View File

@ -257,14 +257,16 @@ PartitionCoreModule::doInit()
cDebug() << Logger::SubEntry << "node\tcapacity\tname\tprettyName"; cDebug() << Logger::SubEntry << "node\tcapacity\tname\tprettyName";
for ( auto device : devices ) for ( auto device : devices )
{ {
cDebug() << Logger::SubEntry << Logger::Pointer( device );
if ( device ) if ( device )
{ {
// Gives ownership of the Device* to the DeviceInfo object // Gives ownership of the Device* to the DeviceInfo object
auto deviceInfo = new DeviceInfo( device ); auto deviceInfo = new DeviceInfo( device );
m_deviceInfos << deviceInfo; m_deviceInfos << deviceInfo;
cDebug() << Logger::SubEntry << device->deviceNode() << device->capacity() << device->name() cDebug() << Logger::SubEntry
<< device->prettyName(); << device->deviceNode()
<< device->capacity()
<< Logger::RedactedName( "DevName", device->name() )
<< Logger::RedactedName( "DevNamePretty", device->prettyName() );
} }
else else
{ {
@ -707,10 +709,10 @@ PartitionCoreModule::dumpQueue() const
cDebug() << "# Queue:"; cDebug() << "# Queue:";
for ( auto info : m_deviceInfos ) for ( auto info : m_deviceInfos )
{ {
cDebug() << Logger::SubEntry << "## Device:" << info->device->name(); cDebug() << Logger::SubEntry << "## Device:" << info->device->deviceNode();
for ( const auto& job : info->jobs() ) for ( const auto& job : info->jobs() )
{ {
cDebug() << Logger::SubEntry << "-" << job->prettyName(); cDebug() << Logger::SubEntry << "-" << job->metaObject()->className();
} }
} }
} }

View File

@ -104,14 +104,19 @@ mapForPartition( Partition* partition, const QString& uuid )
// Debugging for inside the loop in createPartitionList(), // Debugging for inside the loop in createPartitionList(),
// so indent a bit // so indent a bit
Logger::CDebug deb; Logger::CDebug deb;
using TR = Logger::DebugRow< const char* const, const QString& >; using TR = Logger::DebugRow< const char* const, const QString >;
// clang-format off
deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode() deb << Logger::SubEntry << "mapping for" << partition->partitionPath() << partition->deviceNode()
<< TR( "partlabel", map[ "partlabel" ].toString() ) << TR( "partuuid", map[ "partuuid" ].toString() ) << TR( "partlabel", map[ "partlabel" ].toString() )
<< TR( "parttype", map[ "parttype" ].toString() ) << TR( "partattrs", map[ "partattrs" ].toString() ) << TR( "partition-uuid (partuuid)", Logger::RedactedName( "PartUUID", map[ "partuuid" ].toString() ) )
<< TR( "mountPoint:", PartitionInfo::mountPoint( partition ) ) << TR( "fs:", map[ "fs" ].toString() ) << TR( "parttype", map[ "parttype" ].toString() )
<< TR( "fsName", map[ "fsName" ].toString() ) << TR( "uuid", uuid ) << TR( "partattrs", map[ "partattrs" ].toString() )
<< TR( "mountPoint:", PartitionInfo::mountPoint( partition ) )
<< TR( "fs:", map[ "fs" ].toString() )
<< TR( "fsName", map[ "fsName" ].toString() )
<< TR( "filesystem-uuid (uuid)", Logger::RedactedName( "FSUUID", uuid ) )
<< TR( "claimed", map[ "claimed" ].toString() ); << TR( "claimed", map[ "claimed" ].toString() );
// clang-format on
if ( partition->roles().has( PartitionRole::Luks ) ) if ( partition->roles().has( PartitionRole::Luks ) )
{ {
const FileSystem& fsRef = partition->fileSystem(); const FileSystem& fsRef = partition->fileSystem();