Add loading of LUKS mapping offset and length (#760080)

Also load the starting offset and length of the active dm-crypt mapping
into the LUKS_Info module from the dmsetup output.  This provides the
location and size of the encrypted data within the underlying block
device.

Note that dmsetup reports in units of 512 bytes sectors [1], the GParted
LUKS_Info module uses bytes and GParted Partition objects work in device
sector size units.  However the actual sector size of a dm-crypt mapping
[2] is the same as that of the underlying block device [3].

    # modprobe scsi_debug dev_size_mb=128 sector_size=4096
    # fgrep scsi_debug /sys/block/*/device/model
    /sys/block/sdd/device/model:scsi_debug
    # parted /dev/sde print
    Error: /dev/sde: unrecognised disk label
    Model: Linux scsi_debug (scsi)
    Disk /dev/sde: 134MB
[3] Sector size (logical/physical): 4096B/4096B
    Partition Table: unknown

    # cryptsetup luksFormat /dev/sde
    # cryptsetup luksOpen /dev/sde sde_crypt
    # parted /dev/mapper/sde_crypt print
    Error: /dev/mapper/sde_crypt: unrecognised disk label
    Model: Linux device-mapper (crypt) (dm)
    Disk /dev/mapper/sde_crypt: 132MB
[2] Sector size (logical/physical): 4096B/4096B
    Partition Table: unknown

    # cryptsetup status sde_crypt
    /dev/mapper/sde_crypt is active.
      type:  LUKS1
      cipher:  aes-cbc-essiv:sha256
      keysize: 256 bits
      device:  /dev/sde
      offset:  4096 sectors
      size:    258048 sectors
      mode:    read/write
    # dmsetup table --target crypt
    ...
    sde_crypt: 0 258048 crypt aes-cbc-essiv:sha256 0000000000000000000000000000000000000000000000000000000000000000 0 8:64 4096

[1] Both cryptsetup and dmsetup report the offset as 4096 and the size/
length as 258048.  128 MiB / (4096+258048) = 512 byte units, even on a
4096 byte sector size device.

Update debugging of LUKS to this:

    # ./gpartedbin
    ======================
    libparted : 2.4
    ======================
    DEBUG: /dev/sdb5: LUKS closed
    DEBUG: /dev/sdb6: LUKS open mapping /dev/mapper/sdb6_crypt, offset=2097152, length=534773760
    /dev/sde: unrecognised disk label
    DEBUG: /dev/sde: LUKS open mapping /dev/mapper/sde_crypt, offset=2097152, length=132120576

Bug 760080 - Implement read-only LUKS support
This commit is contained in:
Mike Fleetwood 2015-04-19 14:08:20 +01:00 committed by Curtis Gedak
parent ae57f3cd4e
commit 317e444056
4 changed files with 52 additions and 25 deletions

View file

@ -25,16 +25,32 @@
#ifndef GPARTED_LUKS_INFO_H
#define GPARTED_LUKS_INFO_H
#include "../include/Utils.h"
#include <glibmm/ustring.h>
#include <vector>
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
Byte_Value offset; // Offset to the start of the mapping in the underlying block device
Byte_Value length; // Length of the mapping in the underlying block device
};
class LUKS_Info
{
public:
static void load_cache();
static Glib::ustring get_mapping_name( const Glib::ustring & path );
static const LUKS_Mapping & get_cache_entry( const Glib::ustring & path );
private:
static std::vector<LUKS_Mapping> luks_mapping_cache;
};
}//GParted

View file

@ -1425,12 +1425,13 @@ void GParted_Core::set_device_one_partition( Device & device, PedDevice * lp_dev
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() )
LUKS_Mapping mapping = LUKS_Info::get_cache_entry( partition.get_path() );
if ( mapping.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;
<< ": LUKS open mapping " << DEV_MAPPER_PATH << mapping.name << ", offset=" << mapping.offset
<< ", length=" << mapping.length << std::endl;
}
void GParted_Core::set_partition_label_and_uuid( Partition & partition )

View file

@ -18,6 +18,7 @@
#include "../include/Utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@ -25,18 +26,10 @@
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;
// {name="sdb6_crypt", major=8, minor=22, path="/dev/sdb6", offset=2097152, length=534773760}
std::vector<LUKS_Mapping> LUKS_Info::luks_mapping_cache;
void LUKS_Info::load_cache()
{
@ -63,9 +56,11 @@ void LUKS_Info::load_cache()
std::vector<Glib::ustring> fields;
Utils::tokenize( lines[i], fields, " " );
const unsigned DMCRYPT_FIELD_Name = 0;
const unsigned DMCRYPT_FIELD_length = 2;
const unsigned DMCRYPT_FIELD_devpath = 7;
const unsigned DMCRYPT_FIELD_offset = 8;
if ( fields.size() <= DMCRYPT_FIELD_devpath )
if ( fields.size() <= DMCRYPT_FIELD_offset )
continue;
// Extract LUKS mapping name
@ -81,8 +76,8 @@ void LUKS_Info::load_cache()
luks_map.minor = 0UL;
luks_map.path.clear();
Glib::ustring devpath = fields[DMCRYPT_FIELD_devpath];
unsigned long maj = 0;
unsigned long min = 0;
unsigned long maj = 0UL;
unsigned long min = 0UL;
if ( devpath.length() > 0 && devpath[0] == '/' )
luks_map.path = devpath;
else if ( sscanf( devpath.c_str(), "%lu:%lu", &maj, &min ) == 2 )
@ -93,20 +88,34 @@ void LUKS_Info::load_cache()
else
continue;
// Extract LUKS offset and length. Dm-crypt reports all sizes in units of
// 512 byte sectors.
luks_map.offset = -1LL;
luks_map.length = -1LL;
Byte_Value offset = atoll( fields[DMCRYPT_FIELD_offset].c_str() );
Byte_Value length = atoll( fields[DMCRYPT_FIELD_length].c_str() );
if ( offset > 0LL && length > 0LL )
{
luks_map.offset = offset * 512LL;
luks_map.length = length * 512LL;
}
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 )
// Return LUKS cache entry for the named underlying block device path,
// or not found substitute when no entry exists.
const LUKS_Mapping & LUKS_Info::get_cache_entry( 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;
return luks_mapping_cache[i];
}
// Second scan the cache looking for an underlying block device major, minor
@ -124,12 +133,13 @@ Glib::ustring LUKS_Info::get_mapping_name( const Glib::ustring & path )
// query for the same path.
luks_mapping_cache[i].path = path;
return luks_mapping_cache[i].name;
return luks_mapping_cache[i];
}
}
}
return "";
static LUKS_Mapping not_found = {"", 0UL, 0UL, "", -1LL, -1LL};
return not_found;
}
//Private methods

View file

@ -33,8 +33,8 @@ FS luks::get_filesystem_support()
bool luks::is_busy( const Glib::ustring & path )
{
Glib::ustring name = LUKS_Info::get_mapping_name( path );
return ! name.empty();
LUKS_Mapping mapping = LUKS_Info::get_cache_entry( path );
return ! mapping.name.empty();
}
} //GParted