Also erase all Promise FastTrack RAID signatures (#220)

User reported that GParted didn't clear a pdc (Promise FastTrack) RAID
signature [1].  Reproduce this issue by creating a 16 MiB - 512 byte
test image with Promise FastTrack RAID signatures at all recognised
offsets [2].
    $ python << 'EOF'
    signature = b'Promise Technology, Inc.'
    import os
    fd = os.open('/tmp/test.img', os.O_CREAT|os.O_WRONLY)
    os.ftruncate(fd, 16*1024*1024 - 512)
    for offset in [63, 255, 256, 16, 399, 591, 675, 735, 911, 974, 991, 951, 3087]:
        os.lseek(fd, -(offset*512), os.SEEK_END)
        os.write(fd, signature)
    os.close(fd)
    EOF

Then use GParted Format to > Cleared.
    $ sudo ./gpartedbin /tmp/test.img

Afterwards blkid, and therefore GParted, still recognises this as a
Promise FastTrack RAID member.
    $ blkid /tmp/test.img
    /tmp/test.img: TYPE="promise_fasttrack_raid_member"

This is because the test image still contains multiple signatures.
    $ hexdump -C /tmp/test.img | grep Promise
    00e7e000  50 72 6f 6d 69 73 65 20  54 65 63 ...  |Promise Technolo|
    00fce000  50 72 6f 6d 69 73 65 20  54 65 63 ...  |Promise Technolo|
    00fdfe00  50 72 6f 6d 69 73 65 20  54 65 63 ...  |Promise Technolo|
    00ff8000  50 72 6f 6d 69 73 65 20  54 65 63 ...  |Promise Technolo|

Used a test image not an exact multiple of MiBs because drives generally
aren't an exact MiB multiple in size either and as the clearing of ZFS
labels L2 and L3 by writes of zeros at the end of the drive is rounded
to 256 KiBs there will be sectors after that not zeroed where other
Promise signatures remain.  The above signatures map back to these
sectors before the end:
    16*1024*1024 - 512 = 16776704
                                    512b sectors   KiB
    (0x00e7e000 - 16776704) / 512 = -3087          -1543.5
    (0x00fce000 - 16776704) / 512 =  -399           -199.5
    (0x00fdfe00 - 16776704) / 512 =  -256           -128
    (0x00ff8000 - 16776704) / 512 =   -63           -31.5
Promise FastTrack RAID signatures are always at multiples 512-byte
sectors (code uses left shift 9 to convert from sectors to byte offset)
[2].

Fix this by:
1. Replace existing zeroing of 3 ranges relative to the end of the
   device to be a single range covering the ZFS labels L2 and L3 to the
   end of the drive.  This will also clear the SWRaid 0.90 & 1.0
   super blocks, the Nilfs2 secondary super block, the Intel Software
   RAID signature found not zeroed in the unaligned unit test case and
   the above Promise FastTrack RAID signatures at -199.5 KiB and later.
2. Add zeroing of the final Promise FastTrack RAID signature at sector
   -3087.

Performed a review of all the other ATARAID super blocks detected by
blkid (files *_raid.c) [3] and they are all located within the last 11
sectors so will be zeroed by case 1. above.

[1] GParted forum thread: How to remove a ataraid partition ?
    http://gparted-forum.surf4.info/viewtopic.php?id=18104

[2] blkid from util-linux promise_raid.c:probe_pdcraid()
    https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libblkid/src/superblocks/promise_raid.c?h=v2.38.1#n27

[3] blkid RAID member detection (files *_raid.c)
    https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libblkid/src/superblocks/?h=v2.38.1

Closes #220 - Format to Cleared not clearing "pdc" ataraid signature
This commit is contained in:
Mike Fleetwood 2023-01-22 11:44:31 +00:00 committed by Curtis Gedak
parent 3dfc7ef4e4
commit 1c97eedd11
1 changed files with 35 additions and 53 deletions

View File

@ -3771,70 +3771,52 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
overall_success &= device_is_open;
}
//Erase all file system super blocks, including their signatures. The specified
// byte ranges are converted to whole sectors (as disks fundamentally only read
// or write whole sectors) and written using ped_geometry_write(). Therefore
// don't try to surgically overwrite just the few bytes of each signature as this
// code overwrites whole sectors and it embeds more knowledge that is necessary.
// Erase all file system super blocks, including their signatures. The specified
// byte ranges are converted to whole sectors (as disks fundamentally only read or
// write whole sectors) and written using ped_geometry_write(). Therefore don't
// try to surgically overwrite just the few bytes of each signature as this code
// overwrites whole sectors and it embeds more knowledge than is necessary.
//
// First byte range from offset 0 of length 512 KiB covers the primary super
// block of all currently supported file systems and is also likely to include
// future file system super blocks too. Only a few file systems have super
// blocks and signatures located elsewhere.
// First byte range from offset 0, length 512 KiB covers ZFS Labels L0 and L1 and
// all other super blocks at the start of the device.
// ZFS On-Disk Specification
// http://www.giis.co.in/Zfs_ondiskformat.pdf
//
// Btrfs super blocks are located at: 64 KiB, 64 MiB, 256 GiB and 1 PiB.
// (The super block at 64 KiB will be erased by the zeroing from offset 0. Other
// super block mirror copies need to be explicitly cleared).
// https://btrfs.wiki.kernel.org/index.php/On-disk_Format#Superblock
// Last byte range from offset -512 KiB (from the end), length 768 KiB covers ZFS
// Labels L2 and L3 and other super blocks at the end of the device. Includes:
// * Linux Software RAID metadata 0.90 and 1.0
// * secondary Nilfs2 super block
// * Almost all the various ATARAID types
//
// ZFS labels are 256 KiB in size and 4 copies are stored on every member device,
// 2 at the beginning and 2 at the end of the device, aligned to 256 KiB. (The
// front two labels, L0 and L1, will be erased by the zeroing from offset 0. The
// back two labels, L2 and L3, need to be explicitly cleared).
// Reference:
// ZFS On-Disk Specification
// http://maczfs.googlecode.com/files/ZFSOnDiskFormat.pdf
// Not covered by the above are:
// * Btrfs super block mirror copies
// * One possible location of Promise FastTrack RAID super block
//
// Linux Software RAID metadata 0.90 stores it's super block at 64 KiB before the
// end of the device, aligned to 64 KiB boundary. Length 4 KiB.
// Ref: mdadm/super0.c load_super0()
// mdadm/md_p.h #define MD_NEW_SIZE_SECTORS(x) ...
// Btrfs super blocks are located at: 64 KiB, 64 MiB, 256 GiB and 1 PiB. The
// super block at 64 KiB will be erased by the zeroing from offset 0. The super
// block mirror copies need to be explicitly cleared.
// Btrfs: On-disk Format, Superblock
// https://btrfs.wiki.kernel.org/index.php/On-disk_Format#Superblock
//
// Linux Software RAID metadata 1.0 stores it's super block at 8 KiB before the
// end of the device, aligned to 4 KiB boundary. Length 4 KiB. (Metadata 1.1
// and 1.2 store their super blocks at 0 KiB and 4 KiB respectively so will be
// erased by the zeroing from offset 0).
// Ref: mdadm/super1.c load_super1()
// #define MAX_SB_SIZE 4096
//
// Nilfs2 secondary super block is located at the last whole 4 KiB block.
// Ref: nilfs-utils-2.1.4/include/nilfs2_fs.h
// #define NILFS_SB2_OFFSET_BYTES(devsize) ((((devsize) >> 12) - 1) << 12)
//
// NOTE:
// Most of the time partitions are aligned to whole MiBs so the writing of zeros
// at offsets -64 KiB and -8 KiB will be overwriting zeros already just written
// at offset -512 KiB, length 512 KiB. This will double write 12 KiB of zeros.
// However partitions don't have to be MiB aligned and real disk drives generally
// aren't an exact multiple of 1024^2 bytes in size either. So zeroing at offsets
// -64 KiB and -8 KiB with their smaller rounding / alignment requirements will
// write outside the -512 KiB zeroed region and needs to be kept. Because of the
// small amount of double writing it is not worth the effort to suppress it when
// not needed.
// Promise FastTrack RAID super block may be located at any of these 512-byte
// sectors before the end of the device: -16, -63, -255, -256, -399, -591, -675,
// -753, -911, -951, -974, -991, -3087. All from -991 and smaller offsets from
// the end of the device will be erased by the zeroing from -512 KiB. Possible
// location -3087 must be explicitly cleared.
// util-linux v2.38.1: libblkid/src/subperblocks/promise_raid.c:probe_pdcraid()
// https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/libblkid/src/superblocks/promise_raid.c?h=v2.38.1#n27
struct {
Byte_Value offset; //Negative offsets work backwards from the end of the partition
Byte_Value rounding; //Minimum desired rounding for offset
Byte_Value offset; // Negative offsets work backwards from the end of the partition
Byte_Value rounding; // Minimum desired rounding for offset
Byte_Value length;
} ranges[] = {
//offset , rounding , length
{ 0LL , 1LL , 512LL * KIBIBYTE }, // All primary super blocks
//offset , rounding , length
{ 0LL , 1LL , 512LL * KIBIBYTE }, // Super blocks at start
{ 64LL * MEBIBYTE, 1LL , 4LL * KIBIBYTE }, // Btrfs super block mirror copy
{ 256LL * GIBIBYTE, 1LL , 4LL * KIBIBYTE }, // Btrfs super block mirror copy
{ 1LL * PEBIBYTE, 1LL , 4LL * KIBIBYTE }, // Btrfs super block mirror copy
{ -512LL * KIBIBYTE, 256LL * KIBIBYTE, 512LL * KIBIBYTE }, // ZFS labels L2 and L3
{ -64LL * KIBIBYTE, 64LL * KIBIBYTE, 4LL * KIBIBYTE }, // SWRaid metadata 0.90 super block
{ -8LL * KIBIBYTE, 4LL * KIBIBYTE, 8LL * KIBIBYTE } // @-8K SWRaid metadata 1.0 super block
// and @-4K Nilfs2 secondary super block
{ -3087LL * 512LL , 1LL , 512LL }, // Promise FastTrack RAID super block
{ -512LL * KIBIBYTE, 256LL * KIBIBYTE, 768LL * KIBIBYTE } // Super blocks at end
} ;
for ( unsigned int i = 0 ; overall_success && i < sizeof( ranges ) / sizeof( ranges[0] ) ; i ++ )
{