Tomas Bzatek 63ea2b
From eb917d346bc8592924c5f6566b01841176c53c8c Mon Sep 17 00:00:00 2001
Tomas Bzatek 63ea2b
From: Tomas Bzatek <tbzatek@redhat.com>
Tomas Bzatek 63ea2b
Date: Mon, 22 Aug 2022 16:27:11 +0200
Tomas Bzatek 63ea2b
Subject: [PATCH] udiskslinuxblock: Only permit ATA Secure Erase during
Tomas Bzatek 63ea2b
 Format() on a whole block device
Tomas Bzatek 63ea2b
Tomas Bzatek 63ea2b
ATA Secure Erase requested as an option to the Format() method call used
Tomas Bzatek 63ea2b
to perform the actual erase on a whole drive object it looked up. When
Tomas Bzatek 63ea2b
Format() was called on a partition, this led to data loss on a whole drive.
Tomas Bzatek 63ea2b
This commit adds a safeguard to check that the Format() is requested
Tomas Bzatek 63ea2b
on a whole block device.
Tomas Bzatek 63ea2b
Tomas Bzatek 63ea2b
Severity of this issue was slightly lowered by a failure to submit
Tomas Bzatek 63ea2b
the ATA Secure erase command in case some filesystem was mounted
Tomas Bzatek 63ea2b
at that point.
Tomas Bzatek 63ea2b
---
Tomas Bzatek 63ea2b
 src/udiskslinuxblock.c | 16 ++++++++++++++++
Tomas Bzatek 63ea2b
 1 file changed, 16 insertions(+)
Tomas Bzatek 63ea2b
Tomas Bzatek 63ea2b
diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c
Tomas Bzatek 63ea2b
index d1da94edf..db0ed2bf6 100644
Tomas Bzatek 63ea2b
--- a/src/udiskslinuxblock.c
Tomas Bzatek 63ea2b
+++ b/src/udiskslinuxblock.c
Tomas Bzatek 63ea2b
@@ -2354,6 +2354,7 @@ erase_ata_device (UDisksBlock   *block,
Tomas Bzatek 63ea2b
 {
Tomas Bzatek 63ea2b
   gboolean ret = FALSE;
Tomas Bzatek 63ea2b
   UDisksObject *drive_object = NULL;
Tomas Bzatek 63ea2b
+  UDisksLinuxBlockObject *block_object = NULL;
Tomas Bzatek 63ea2b
   UDisksDriveAta *ata = NULL;
Tomas Bzatek 63ea2b
 
Tomas Bzatek 63ea2b
   drive_object = udisks_daemon_find_object (daemon, udisks_block_get_drive (block));
Tomas Bzatek 63ea2b
@@ -2369,6 +2370,20 @@ erase_ata_device (UDisksBlock   *block,
Tomas Bzatek 63ea2b
       goto out;
Tomas Bzatek 63ea2b
     }
Tomas Bzatek 63ea2b
 
Tomas Bzatek 63ea2b
+  /* Reverse check to ensure we're erasing whole block device and not a partition */
Tomas Bzatek 63ea2b
+  block_object = udisks_linux_drive_object_get_block (UDISKS_LINUX_DRIVE_OBJECT (drive_object), FALSE /* get_hw */);
Tomas Bzatek 63ea2b
+  if (block_object == NULL)
Tomas Bzatek 63ea2b
+    {
Tomas Bzatek 63ea2b
+      g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED, "Couldn't find a block device for the drive to erase");
Tomas Bzatek 63ea2b
+      goto out;
Tomas Bzatek 63ea2b
+    }
Tomas Bzatek 63ea2b
+  if (g_strcmp0 (g_dbus_object_get_object_path (G_DBUS_OBJECT (object)),
Tomas Bzatek 63ea2b
+                 g_dbus_object_get_object_path (G_DBUS_OBJECT (block_object))) != 0)
Tomas Bzatek 63ea2b
+    {
Tomas Bzatek 63ea2b
+      g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED, "ATA secure erase needs to be performed on a whole block device");
Tomas Bzatek 63ea2b
+      goto out;
Tomas Bzatek 63ea2b
+    }
Tomas Bzatek 63ea2b
+
Tomas Bzatek 63ea2b
   /* sleep a tiny bit here to avoid the secure erase code racing with
Tomas Bzatek 63ea2b
    * programs spawned by udev
Tomas Bzatek 63ea2b
    */
Tomas Bzatek 63ea2b
@@ -2382,6 +2397,7 @@ erase_ata_device (UDisksBlock   *block,
Tomas Bzatek 63ea2b
  out:
Tomas Bzatek 63ea2b
   g_clear_object (&ata;;
Tomas Bzatek 63ea2b
   g_clear_object (&drive_object);
Tomas Bzatek 63ea2b
+  g_clear_object (&block_object);
Tomas Bzatek 63ea2b
   return ret;
Tomas Bzatek 63ea2b
 }
Tomas Bzatek 63ea2b