Add initial loading of LUKS mapping details (#760080)
Load basic details of active Device-mapper encryption mappings from the kernel. Use dmsetup active targets. # cryptsetup luksFormat /dev/sdb5 # cryptsetup luksFormat /dev/sdb6 # cryptsetup luksOpen /dev/sdb6 sdb6_crypt # ls -l /dev/mapper/sdb6_crypt /dev/dm-0 lrwxrwxrwx. 1 root root 7 Nov 15 09:03 /dev/mapper/sdb6_crypt -> ../dm-0 brw-rw----. 1 root disk 253, 0 Nov 15 09:03 /dev/dm-0 # ls -l /dev/sdb6 brw-rw----. 1 root disk 8, 22 Nov 15 09:02 /dev/sdb6 # dmsetup table --target crypt sdb6_crypt: 0 1044480 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:22 4096 So far just load the mapping name and underlying block device reference (path or major, minor pair). Note that all supported kernels appear to report the underlying block device as major, minor pair in the dmsetup output. Underlying block device paths are added to the cache when found during a search to avoid stat(2) call on subsequent searches for the same path. Prints debugging to show results, like this: # ./gpartedbin ====================== libparted : 2.4 ====================== DEBUG: /dev/sdb5: LUKS closed DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt Bug 760080 - Implement read-only LUKS support
This commit is contained in:
parent
1b55dfad5b
commit
b77a6be76b
|
@ -92,6 +92,7 @@ private:
|
|||
void set_device_partitions( Device & device, PedDevice* lp_device, PedDisk* lp_disk ) ;
|
||||
void set_device_one_partition( Device & device, PedDevice * lp_device, FILESYSTEM fstype,
|
||||
std::vector<Glib::ustring> & messages );
|
||||
void debug_luks_partition( Partition & partition );
|
||||
void set_partition_label_and_uuid( Partition & partition );
|
||||
static FILESYSTEM detect_filesystem_internal( PedDevice * lp_device, PedPartition * lp_partition );
|
||||
static FILESYSTEM detect_filesystem( PedDevice * lp_device, PedPartition * lp_partition,
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (C) 2015 Mike Fleetwood
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/* LUKS_Info
|
||||
*
|
||||
* Cache of active Linux kernel Device-mapper encryption mappings.
|
||||
* (Named LUKS because only encryption using the LUKS on disk format is
|
||||
* recognised and handled).
|
||||
*/
|
||||
|
||||
#ifndef GPARTED_LUKS_INFO_H
|
||||
#define GPARTED_LUKS_INFO_H
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
namespace GParted
|
||||
{
|
||||
|
||||
class LUKS_Info
|
||||
{
|
||||
public:
|
||||
static void load_cache();
|
||||
static Glib::ustring get_mapping_name( const Glib::ustring & path );
|
||||
};
|
||||
|
||||
}//GParted
|
||||
|
||||
#endif /* GPARTED_LUKS_INFO_H */
|
|
@ -24,6 +24,7 @@ EXTRA_DIST = \
|
|||
GParted_Core.h \
|
||||
HBoxOperations.h \
|
||||
LVM2_PV_Info.h \
|
||||
LUKS_Info.h \
|
||||
Operation.h \
|
||||
OperationChangeUUID.h \
|
||||
OperationCheck.h \
|
||||
|
|
|
@ -21,6 +21,7 @@ src/FileSystem.cc
|
|||
src/GParted_Core.cc
|
||||
src/HBoxOperations.cc
|
||||
src/LVM2_PV_Info.cc
|
||||
src/LUKS_Info.cc
|
||||
src/OperationChangeUUID.cc
|
||||
src/OperationCopy.cc
|
||||
src/OperationCheck.cc
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "../include/DMRaid.h"
|
||||
#include "../include/FS_Info.h"
|
||||
#include "../include/LVM2_PV_Info.h"
|
||||
#include "../include/LUKS_Info.h"
|
||||
#include "../include/Operation.h"
|
||||
#include "../include/OperationCopy.h"
|
||||
#include "../include/Partition.h"
|
||||
|
@ -161,6 +162,7 @@ void GParted_Core::set_devices_thread( std::vector<Device> * pdevices )
|
|||
LVM2_PV_Info::clear_cache(); // Cache automatically loaded if and when needed
|
||||
btrfs::clear_cache(); // Cache incrementally loaded if and when needed
|
||||
SWRaid_Info::load_cache();
|
||||
LUKS_Info::load_cache();
|
||||
|
||||
init_maps() ;
|
||||
|
||||
|
@ -1299,6 +1301,9 @@ void GParted_Core::set_device_partitions( Device & device, PedDevice* lp_device,
|
|||
partition_temp->add_paths( pp_info.get_alternate_paths( partition_temp->get_path() ) );
|
||||
set_flags( *partition_temp, lp_partition );
|
||||
|
||||
if ( filesystem == FS_LUKS )
|
||||
debug_luks_partition( *partition_temp );
|
||||
|
||||
if ( partition_temp->busy && partition_temp->partition_number > device.highest_busy )
|
||||
device.highest_busy = partition_temp->partition_number;
|
||||
break ;
|
||||
|
@ -1405,6 +1410,9 @@ void GParted_Core::set_device_one_partition( Device & device, PedDevice * lp_dev
|
|||
partition_temp->messages = messages;
|
||||
partition_temp->add_paths( pp_info.get_alternate_paths( partition_temp->get_path() ) );
|
||||
|
||||
if ( fstype == FS_LUKS )
|
||||
debug_luks_partition( *partition_temp );
|
||||
|
||||
if ( partition_temp->busy )
|
||||
device.highest_busy = 1;
|
||||
|
||||
|
@ -1413,6 +1421,17 @@ void GParted_Core::set_device_one_partition( Device & device, PedDevice * lp_dev
|
|||
device.partitions.push_back_adopt( partition_temp );
|
||||
}
|
||||
|
||||
void GParted_Core::debug_luks_partition( Partition & partition )
|
||||
{
|
||||
// FIXME: Temporary debugging of LUKS mapping.
|
||||
Glib::ustring name = LUKS_Info::get_mapping_name( partition.get_path() );
|
||||
if ( name.empty() )
|
||||
std::cout << "DEBUG: " << partition.get_path() << ": LUKS closed" << std::endl;
|
||||
else
|
||||
std::cout << "DEBUG: " << partition.get_path()
|
||||
<< ": LUKS open mapping " << DEV_MAPPER_PATH << name << std::endl;
|
||||
}
|
||||
|
||||
void GParted_Core::set_partition_label_and_uuid( Partition & partition )
|
||||
{
|
||||
FS_Info fs_info; // Use cache of file system information
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/* Copyright (C) 2015 Mike Fleetwood
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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 "../include/LUKS_Info.h"
|
||||
#include "../include/Utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace GParted
|
||||
{
|
||||
|
||||
struct LUKS_Mapping
|
||||
{
|
||||
Glib::ustring name; // Name of the dm-crypt mapping
|
||||
unsigned long major; // Major device number of the underlying block device
|
||||
unsigned long minor; // Minor device number of the underlying block device
|
||||
Glib::ustring path; // Path of the underlying block device
|
||||
};
|
||||
|
||||
// Cache of active dm-crypt mappings.
|
||||
// Example entry:
|
||||
// {name="sdb6_crypt", major=8, minor=22, path="/dev/sdb6"}
|
||||
static std::vector<LUKS_Mapping> luks_mapping_cache;
|
||||
|
||||
void LUKS_Info::load_cache()
|
||||
{
|
||||
luks_mapping_cache.clear();
|
||||
|
||||
Glib::ustring output;
|
||||
Glib::ustring error;
|
||||
Utils::execute_command( "dmsetup table --target crypt", output, error, true );
|
||||
// dmsetup output is one line per dm-crypt mapping containing fields:
|
||||
// NAME: START LENGTH TARGET CIPHER KEY IVOFFSET DEVPATH OFFSET ...
|
||||
// or the text:
|
||||
// No devices found
|
||||
// First 4 fields are defined by the dmsetup program by the print call in the
|
||||
// _status() function:
|
||||
// https://git.fedorahosted.org/cgit/lvm2.git/tree/tools/dmsetup.c?id=v2_02_118#n1715
|
||||
// Field 5 onwards are called parameters and documented in the kernel source:
|
||||
// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/device-mapper/dm-crypt.txt?id=v4.0
|
||||
|
||||
std::vector<Glib::ustring> lines;
|
||||
Utils::tokenize( output, lines, "\n" );
|
||||
for ( unsigned int i = 0 ; i < lines.size() ; i ++ )
|
||||
{
|
||||
LUKS_Mapping luks_map;
|
||||
std::vector<Glib::ustring> fields;
|
||||
Utils::tokenize( lines[i], fields, " " );
|
||||
const unsigned DMCRYPT_FIELD_Name = 0;
|
||||
const unsigned DMCRYPT_FIELD_devpath = 7;
|
||||
|
||||
if ( fields.size() <= DMCRYPT_FIELD_devpath )
|
||||
continue;
|
||||
|
||||
// Extract LUKS mapping name
|
||||
Glib::ustring name = fields[DMCRYPT_FIELD_Name];
|
||||
size_t len = name.length();
|
||||
if ( len <= 1 || name[len-1] != ':' )
|
||||
continue;
|
||||
luks_map.name = name.substr( 0, len-1 );
|
||||
|
||||
// Extract LUKS underlying device containing the encrypted data. May be
|
||||
// either a device name (/dev/sda1) or major, minor pair (8:1).
|
||||
luks_map.major = 0UL;
|
||||
luks_map.minor = 0UL;
|
||||
luks_map.path.clear();
|
||||
Glib::ustring devpath = fields[DMCRYPT_FIELD_devpath];
|
||||
unsigned long maj = 0;
|
||||
unsigned long min = 0;
|
||||
if ( devpath.length() > 0 && devpath[0] == '/' )
|
||||
luks_map.path = devpath;
|
||||
else if ( sscanf( devpath.c_str(), "%lu:%lu", &maj, &min ) == 2 )
|
||||
{
|
||||
luks_map.major = maj;
|
||||
luks_map.minor = min;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
luks_mapping_cache.push_back( luks_map );
|
||||
}
|
||||
}
|
||||
|
||||
// Return name of the active LUKS mapping for the underlying block device path,
|
||||
// or "" when no such mapping exists.
|
||||
Glib::ustring LUKS_Info::get_mapping_name( const Glib::ustring & path )
|
||||
{
|
||||
// First scan the cache looking for an underlying block device path match.
|
||||
// (Totally in memory)
|
||||
for ( unsigned int i = 0 ; i < luks_mapping_cache.size() ; i ++ )
|
||||
{
|
||||
if ( path == luks_mapping_cache[i].path )
|
||||
return luks_mapping_cache[i].name;
|
||||
}
|
||||
|
||||
// Second scan the cache looking for an underlying block device major, minor
|
||||
// match. (Requires single stat(2) call per search)
|
||||
struct stat sb;
|
||||
if ( stat( path.c_str(), &sb ) == 0 && S_ISBLK( sb.st_mode ) )
|
||||
{
|
||||
unsigned long maj = major( sb.st_rdev );
|
||||
unsigned long min = minor( sb.st_rdev );
|
||||
for ( unsigned int i = 0 ; i < luks_mapping_cache.size() ; i ++ )
|
||||
{
|
||||
if ( maj == luks_mapping_cache[i].major && min == luks_mapping_cache[i].minor )
|
||||
{
|
||||
// Store path in cache to avoid stat() call on subsequent
|
||||
// query for the same path.
|
||||
luks_mapping_cache[i].path = path;
|
||||
|
||||
return luks_mapping_cache[i].name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
//Private methods
|
||||
|
||||
}//GParted
|
|
@ -35,6 +35,7 @@ gpartedbin_SOURCES = \
|
|||
GParted_Core.cc \
|
||||
HBoxOperations.cc \
|
||||
LVM2_PV_Info.cc \
|
||||
LUKS_Info.cc \
|
||||
Operation.cc \
|
||||
OperationChangeUUID.cc \
|
||||
OperationCheck.cc \
|
||||
|
|
Loading…
Reference in New Issue