Use libparted geometry to bound writing in erase_filesystem_signatures()
The code in erase_filesystem_signatures() used libparted ped_device_write() which allowed any sector in the whole disk device to be written. The code only depended on calculations of somewhat complicated zero offset ranges and the start partition offset to ensure that it didn't zero sectors outside the target partition. The code doesn't overwrite partition boundaries, but there have been updates and bug fixes to the calculation code. To improve the safety create a libparted geometry representing the partition, or whole disk device, to be cleared and use ped_geometry_write() so that libparted enforces writes are only within the partition boundary being erased. Deliberately breaking erase_filesystem_signatures() code so that it tries to write past the end of the partition produces this dialog: Libparted Error (-) Attempt to write sectors 1024000-1024007 outside of partition on /dev/sdb. [ Cancel ] [ Ignore ] And trying to write before the start of the partition produces this dialog: Libparted Bug (-) Assert (offset >= 0) at cs/geom.c:375 in function ped_geometry_write() failed. [ No ] Followed by GParted aborting and producing a core dump. Not ideal from libparted, but it does prevent GParted writing outside the partition boundaries and only occurs in the case of a bug in erase_filesystem_signatures() which is exercised on every Create and Format Partition operation and now also unit tested. So not something we will let through to the users.
This commit is contained in:
parent
5255a39137
commit
ad434bb651
|
@ -3742,6 +3742,7 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
|
||||||
PedDevice* lp_device = NULL ;
|
PedDevice* lp_device = NULL ;
|
||||||
PedDisk* lp_disk = NULL ;
|
PedDisk* lp_disk = NULL ;
|
||||||
PedPartition* lp_partition = NULL ;
|
PedPartition* lp_partition = NULL ;
|
||||||
|
PedGeometry *lp_geom = NULL;
|
||||||
bool device_is_open = false ;
|
bool device_is_open = false ;
|
||||||
Byte_Value bufsize = 4LL * KIBIBYTE ;
|
Byte_Value bufsize = 4LL * KIBIBYTE ;
|
||||||
char * buf = NULL ;
|
char * buf = NULL ;
|
||||||
|
@ -3749,17 +3750,20 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
|
||||||
{
|
{
|
||||||
if ( partition.type == TYPE_UNPARTITIONED )
|
if ( partition.type == TYPE_UNPARTITIONED )
|
||||||
{
|
{
|
||||||
// Virtual partition spanning whole disk device
|
// Whole disk device; create a matching geometry
|
||||||
overall_success = true;
|
lp_geom = ped_geometry_new(lp_device,
|
||||||
|
partition.sector_start,
|
||||||
|
partition.get_sector_length());
|
||||||
}
|
}
|
||||||
else if ( get_disk( lp_device, lp_disk ) )
|
else if ( get_disk( lp_device, lp_disk ) )
|
||||||
{
|
{
|
||||||
// Partitioned device
|
// Partitioned device; copy partition geometry
|
||||||
lp_partition = ped_disk_get_partition_by_sector( lp_disk, partition.get_sector() );
|
lp_partition = ped_disk_get_partition_by_sector( lp_disk, partition.get_sector() );
|
||||||
overall_success = ( lp_partition != NULL );
|
if (lp_partition)
|
||||||
|
lp_geom = ped_geometry_duplicate(&lp_partition->geom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( overall_success && ped_device_open( lp_device ) )
|
if (lp_geom != NULL && ped_device_open(lp_device))
|
||||||
{
|
{
|
||||||
device_is_open = true ;
|
device_is_open = true ;
|
||||||
|
|
||||||
|
@ -3768,7 +3772,7 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
|
||||||
if ( buf )
|
if ( buf )
|
||||||
memset( buf, 0, bufsize ) ;
|
memset( buf, 0, bufsize ) ;
|
||||||
}
|
}
|
||||||
overall_success &= device_is_open;
|
overall_success = device_is_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase all file system super blocks, including their signatures. The specified
|
// Erase all file system super blocks, including their signatures. The specified
|
||||||
|
@ -3877,19 +3881,15 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
|
||||||
Utils::format_size( byte_len, 1 ),
|
Utils::format_size( byte_len, 1 ),
|
||||||
byte_offset ) ) ) ;
|
byte_offset ) ) ) ;
|
||||||
|
|
||||||
// Start sector of the whole disk device or the partition
|
|
||||||
Sector ptn_start = 0LL;
|
|
||||||
if ( lp_partition )
|
|
||||||
ptn_start = lp_partition->geom.start;
|
|
||||||
|
|
||||||
while ( written < byte_len )
|
while ( written < byte_len )
|
||||||
{
|
{
|
||||||
//Write in bufsize amounts. Last write may be smaller but
|
//Write in bufsize amounts. Last write may be smaller but
|
||||||
// will still be a whole number of sectors.
|
// will still be a whole number of sectors.
|
||||||
Byte_Value amount = std::min( bufsize, byte_len - written ) ;
|
Byte_Value amount = std::min( bufsize, byte_len - written ) ;
|
||||||
zero_success = ped_device_write( lp_device, buf,
|
zero_success = ped_geometry_write(lp_geom,
|
||||||
ptn_start + ( byte_offset + written ) / lp_device->sector_size,
|
buf,
|
||||||
amount / lp_device->sector_size );
|
(byte_offset + written) / lp_device->sector_size,
|
||||||
|
amount / lp_device->sector_size);
|
||||||
if ( ! zero_success )
|
if ( ! zero_success )
|
||||||
break ;
|
break ;
|
||||||
written += amount ;
|
written += amount ;
|
||||||
|
@ -3901,6 +3901,8 @@ bool GParted_Core::erase_filesystem_signatures( const Partition & partition, Ope
|
||||||
}
|
}
|
||||||
if ( buf )
|
if ( buf )
|
||||||
free( buf ) ;
|
free( buf ) ;
|
||||||
|
if (lp_geom != NULL)
|
||||||
|
ped_geometry_destroy(lp_geom);
|
||||||
|
|
||||||
//Linux kernel doesn't maintain buffer cache coherency between the whole disk
|
//Linux kernel doesn't maintain buffer cache coherency between the whole disk
|
||||||
// device and partition devices. So even though the file system signatures
|
// device and partition devices. So even though the file system signatures
|
||||||
|
|
Loading…
Reference in New Issue