Don't crash probing libparted unrecognised encrypted file system (#152)

Create a LUKS encrypted partition and open it.  Then either leave the
contents blank or create a file system which libparted doesn't
recognise, such as: exfat, f2fs, lvm2 pv, minix or reiser4.  When
GParted probes the disk device it crashes.

    # echo -n badpassword | cryptsetup luksFormat /dev/sdb11
    # echo -n badpassword | cryptsetup luksOpen /dev/sdb11 sdb11_crypt
    # ./gpartedbin /dev/sdb
    GParted 1.2.0-git
    configuration (none)
    libparted 3.1
    /dev/mapper/sdb11_crypt: unrecognised disk label
    Segmentation fault (core dumped)

Backtrace:
    #0  0x0000000000460f68 in GParted::GParted_Core::detect_filesystem(_PedDevice*, _PedPartition*, std::vector<Glib::ustring, std::allocator<Glib::ustring> >&)
        (lp_device=0x0, lp_partition=0x0, messages=std::vector of length 0, capacity 0)
        at GParted_Core.cc:1235
    #1  0x00000000004615a6 in GParted::GParted_Core::detect_filesystem_in_encryption_mapping(Glib::ustring const&, std::vector<Glib::ustring, std::allocator<Glib::ustring> >&)
        (path=..., messages=std::vector of length 0, capacity 0)
        at GParted_Core.cc:1096
    #2  0x00000000004647c8 in GParted::GParted_Core::set_luks_partition(GParted::PartitionLUKS&)
        (this=this@entry=0x7fff43f974e0, partition=...)
        at GParted_Core.cc:1011
    #3  0x000000000046511b in GParted::GParted_Core::set_device_partitions(GParted::Device&, _PedDevice*, _PedDisk*)
        (this=this@entry=0x7fff43f974e0, device=..., lp_device=0x7efc780008c0, lp_disk=0x7efc78000d10)
        at GParted_Core.cc:883
    #4  0x00000000004658e3 in GParted::GParted_Core::set_device_from_disk(GParted::Device&, Glib::ustring const&)
        (this=this@entry=0x7fff43f974e0, device=..., device_path=...)
        at GParted_Core.cc:704
    #5  0x0000000000465fff in GParted::GParted_Core::set_devices_thread(std::vector<GParted::Device, std::allocator<GParted::Device> >*)
        (this=0x7fff43f974e0, pdevices=0x7fff43f96bc8)
        at GParted_Core.cc:266
    #6  0x00007efc99ba413d in call_thread_entry_slot ()
        at /lib64/libglibmm-2.4.so.1
    #7  0x00007efc97dc8555 in g_thread_proxy ()
        at /lib64/libglib-2.0.so.0
    #8  0x00007efc96ab4ea5 in start_thread () at /lib64/libpthread.so.0
    #9  0x00007efc967dd9fd in clone () at /lib64/libc.so.6

The relevant sequence of events goes like this:
    detect_filesystem_in_encryption_mapping(path, ...)
      lp_device = NULL
      get_device(path, lp_device)
        lp_device = ped_device_get(path.c_str())
        return true
      lp_disk = NULL
      lp_partition = NULL
      get_disk(lp_device, lp_disk)  // + default parameter strict=true
        lp_disk = ped_disk_new(lp_device)
          // No libparted recognised disk label or file system found, so
          // NULL returned.
        destroy_device_and_disk(lp_device, lp_disk)
          ped_device_destroy(lp_device)
          lp_device = NULL
        return false
      detect_filesystem(lp_device, lp_partition, ...)
        path = lp_device->path

The key points are:
1. get_device() created a PedDevice object pointed to by lp_device;
2. get_disk() didn't find a libparted recognised disk label or file
   system but also unexpectedly destroyed the PedDevice object and
   assigned NULL to lp_device;
3. detect_filesystem() dereferenced lp_device assuming it was still
   valid.

Implement the simplest possible fix by telling get_disk() to not
destroy the needed PedDevice object when there's no recognised content.
This is the same as how get_disk() is called in set_device_from_disk().

Closes #152 - GParted crashed when trying to probe an encrypted
              partition containing content that libparted doesn't
              recognise
This commit is contained in:
Mike Fleetwood 2021-04-08 20:45:19 +01:00 committed by Curtis Gedak
parent 20a06d00b5
commit 09df074a92
1 changed files with 2 additions and 2 deletions

View File

@ -1087,8 +1087,8 @@ FSType GParted_Core::detect_filesystem_in_encryption_mapping(const Glib::ustring
// supports one block device to one encryption mapping to one file system. // supports one block device to one encryption mapping to one file system.
PedDisk *lp_disk = NULL; PedDisk *lp_disk = NULL;
PedPartition *lp_partition = NULL; PedPartition *lp_partition = NULL;
if (get_disk(lp_device, lp_disk) && lp_disk->type && lp_disk->type->name && if (get_disk(lp_device, lp_disk, false) && lp_disk && lp_disk->type &&
strcmp(lp_disk->type->name, "loop") == 0 ) lp_disk->type->name && strcmp(lp_disk->type->name, "loop") == 0 )
{ {
lp_partition = ped_disk_next_partition(lp_disk, NULL); lp_partition = ped_disk_next_partition(lp_disk, NULL);
} }