GNU bug report logs -
#79720
libparted: wrong metadata length with empty GPT partition table
Previous Next
To reply to this bug, email your comments to 79720 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Wed, 29 Oct 2025 21:08:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Pascal Hambourg <pascal <at> plouf.fr.eu.org>:
New bug report received and forwarded. Copy sent to
bug-parted <at> gnu.org.
(Wed, 29 Oct 2025 21:08:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Package: parted
Version: 3.6
Severity: minor
Dear maintainers,
When libparted reads an existing empty GPT partition table, it wrongly
creates the main and backup virtual metadata partitions with a length
based on GPT_DEFAULT_PARTITION_ENTRIES (128) instead of the actual
partition table length based on NumberOfPartitionEntries in the GPT
header. Only after an active partition is added (either read from the
on-disk partition table or new), the metadata partitions have the
correct length.
Looking at libparted/label/gpt.c, it seems that gpt_read() initializes
the partition table object with GPT_DEFAULT_PARTITION_ENTRIES and does
not trigger an update of metadata and free space after parsing the GPT
header but only when partitions are added.
(My use case is with partman, the Debian installer partitioning tool
based on libparted. I need to check whether the current GPT metadata
would overlap with U-Boot location for Allwinner sunxi SoCs starting at
offset 8KiB (sector 16). A GPT partition table with a maximum length of
56 entries can be created with gdisk and ends at sector 15 so is
compatible with U-Boot for sunxi. But when the GPT partition table is
empty, the reported metadata length is inaccurate.)
As a workaround, is there a simple reliable way using libparted API to
update metadata without altering the state of the partition table ?
Otherwise, what is the best place and way to fix this in libparted, in
other word make sure metadata and free space are properly updated when
the partition table is empty ?
IIUC it involves _disk_push_update_mode() and _disk_pop_update_mode()
which can be called only in libparted/disk.c.
Information forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Fri, 31 Oct 2025 21:54:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 79720 <at> debbugs.gnu.org (full text, mbox):
On Wed, Oct 29, 2025 at 10:06:23PM +0100, Pascal Hambourg wrote:
> Package: parted
> Version: 3.6
> Severity: minor
>
> Dear maintainers,
>
> When libparted reads an existing empty GPT partition table, it wrongly
> creates the main and backup virtual metadata partitions with a length based
> on GPT_DEFAULT_PARTITION_ENTRIES (128) instead of the actual partition table
> length based on NumberOfPartitionEntries in the GPT header. Only after an
> active partition is added (either read from the on-disk partition table or
> new), the metadata partitions have the correct length.
>
> Looking at libparted/label/gpt.c, it seems that gpt_read() initializes the
> partition table object with GPT_DEFAULT_PARTITION_ENTRIES and does not
> trigger an update of metadata and free space after parsing the GPT header
> but only when partitions are added.
I've tried to figure out where this could be going wrong, but am not
seeing it. When gpt_alloc is called it sets gpt_disk_data->entry_count
to the default. But when gpt_read is called it calls _parse_header, and
parse_header sets entry_count from the value it read from the header
(gpt->NumberOfPartitionEntries).
So as long as ped_disk_new is called the entry_count should be correct
and used everywhere. So I'm not sure how you are seeing the behavior you
are describing.
I do agree that parted has problems with relocated partition tables, I
think the first thing to do there is to detect that and raise an
exception instead of rewriting it to LBA 2.
Brian
--
Brian C. Lane (PST8PDT) - weldr.io - lorax - parted - pykickstart
Information forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Fri, 31 Oct 2025 23:01:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 79720 <at> debbugs.gnu.org (full text, mbox):
On 31/10/2025 at 22:53, Brian C. Lane wrote:
>>
>> When libparted reads an existing empty GPT partition table, it wrongly
>> creates the main and backup virtual metadata partitions with a length based
>> on GPT_DEFAULT_PARTITION_ENTRIES (128) instead of the actual partition table
>> length based on NumberOfPartitionEntries in the GPT header. Only after an
>> active partition is added (either read from the on-disk partition table or
>> new), the metadata partitions have the correct length.
>>
>> Looking at libparted/label/gpt.c, it seems that gpt_read() initializes the
>> partition table object with GPT_DEFAULT_PARTITION_ENTRIES and does not
>> trigger an update of metadata and free space after parsing the GPT header
>> but only when partitions are added.
>
> I've tried to figure out where this could be going wrong, but am not
> seeing it. When gpt_alloc is called it sets gpt_disk_data->entry_count
> to the default. But when gpt_read is called it calls _parse_header, and
> parse_header sets entry_count from the value it read from the header
> (gpt->NumberOfPartitionEntries).
Here is the (trimmed) call chain as I understand it:
ped_disk_new
ped_disk_new_fresh
type->ops->alloc (-> gpt_alloc)
_ped_disk_alloc
gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES
_disk_pop_update_mode <- update metadata and free space
type->ops->read (-> gpt_read)
ped_disk_delete_all
gpt_read_headers
_parse_header
gpt_disk_data->entry_count = gpt->NumberOfPartitionEntries
gpt_read_PE_array
for each active partition entry
_parse_part_entry
ped_disk_add_partition
_disk_push_update_mode
_disk_raw_add
_disk_pop_update_mode <- update metadata and free space
Indeed _parse_header updates entry_count, but then _disk_pop_update_mode
(which updates metadata and free space partitions) is called only if the
partition table has at least one active partition. Or later when a new
partition is created, or the pmbr_boot flag is set.
I quickly tested that surrounding the call to type->ops->read with
_disk_push_update_mode and _disk_pop_update_mode in ped_disk_new seems
to fix the issue:
diff --git a/libparted/disk.c b/libparted/disk.c
index 2d6b9d49..768f4681 100644
--- a/libparted/disk.c
+++ b/libparted/disk.c
@@ -199,8 +199,10 @@ ped_disk_new (PedDevice* dev)
if (!disk)
goto error_close_dev;
+ _disk_push_update_mode (disk);
if (!type->ops->read (disk))
goto error_destroy_disk;
+ _disk_pop_update_mode (disk);
disk->needs_clobber = 0;
ped_device_close (dev);
return disk;
But I am now working on a larger patch which aims to stay in update mode
and avoid useless transient metadata and free space partition updates
until after reading the partition table. Would it be welcome ?
> I do agree that parted has problems with relocated partition tables, I
> think the first thing to do there is to detect that and raise an
> exception instead of rewriting it to LBA 2.
I observed this issue and found related bug #68379. But IMO it is a
totally unrelated issue which should be addressed separately.
Information forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Mon, 03 Nov 2025 21:46:01 GMT)
Full text and
rfc822 format available.
Message #14 received at 79720 <at> debbugs.gnu.org (full text, mbox):
On Sat, Nov 01, 2025 at 12:00:40AM +0100, Pascal Hambourg wrote:
> On 31/10/2025 at 22:53, Brian C. Lane wrote:
> > >
> > > When libparted reads an existing empty GPT partition table, it wrongly
> > > creates the main and backup virtual metadata partitions with a length based
> > > on GPT_DEFAULT_PARTITION_ENTRIES (128) instead of the actual partition table
> > > length based on NumberOfPartitionEntries in the GPT header. Only after an
> > > active partition is added (either read from the on-disk partition table or
> > > new), the metadata partitions have the correct length.
> > >
> > > Looking at libparted/label/gpt.c, it seems that gpt_read() initializes the
> > > partition table object with GPT_DEFAULT_PARTITION_ENTRIES and does not
> > > trigger an update of metadata and free space after parsing the GPT header
> > > but only when partitions are added.
> >
> > I've tried to figure out where this could be going wrong, but am not
> > seeing it. When gpt_alloc is called it sets gpt_disk_data->entry_count
> > to the default. But when gpt_read is called it calls _parse_header, and
> > parse_header sets entry_count from the value it read from the header
> > (gpt->NumberOfPartitionEntries).
>
> Here is the (trimmed) call chain as I understand it:
>
> ped_disk_new
> ped_disk_new_fresh
> type->ops->alloc (-> gpt_alloc)
> _ped_disk_alloc
> gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES
> _disk_pop_update_mode <- update metadata and free space
> type->ops->read (-> gpt_read)
> ped_disk_delete_all
> gpt_read_headers
> _parse_header
> gpt_disk_data->entry_count = gpt->NumberOfPartitionEntries
> gpt_read_PE_array
> for each active partition entry
> _parse_part_entry
> ped_disk_add_partition
> _disk_push_update_mode
> _disk_raw_add
> _disk_pop_update_mode <- update metadata and free space
>
> Indeed _parse_header updates entry_count, but then _disk_pop_update_mode
> (which updates metadata and free space partitions) is called only if the
> partition table has at least one active partition. Or later when a new
> partition is created, or the pmbr_boot flag is set.
Ah, ok. Now it's clear :) Thanks for that.
> I quickly tested that surrounding the call to type->ops->read with
> _disk_push_update_mode and _disk_pop_update_mode in ped_disk_new seems to
> fix the issue:
>
> diff --git a/libparted/disk.c b/libparted/disk.c
> index 2d6b9d49..768f4681 100644
> --- a/libparted/disk.c
> +++ b/libparted/disk.c
> @@ -199,8 +199,10 @@ ped_disk_new (PedDevice* dev)
> if (!disk)
> goto error_close_dev;
> + _disk_push_update_mode (disk);
> if (!type->ops->read (disk))
> goto error_destroy_disk;
> + _disk_pop_update_mode (disk);
> disk->needs_clobber = 0;
> ped_device_close (dev);
> return disk;
This doesn't pass the tests -- gpt_read calls ped_disk_commit_to_dev
when it needs to fix one of the headers, and that has an assert check on
update_mode.
But, while it seems a bit like a kludge, I think we could just do a
push/pop right after doing the read instead of wrapping it. That at
least passes the tests and I don't think it would have any unexpected
side-effects.
> But I am now working on a larger patch which aims to stay in update mode and
> avoid useless transient metadata and free space partition updates until
> after reading the partition table. Would it be welcome ?
I'm open to anything -- but am very reluctant to make large changes
without really good reasons. parted is, for the most part, really stable
and I'm worried about breaking things.
Brian
--
Brian C. Lane (PST8PDT) - weldr.io - lorax - parted - pykickstart
Information forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Tue, 04 Nov 2025 10:00:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 79720 <at> debbugs.gnu.org (full text, mbox):
On 03/11/2025 à 22:45, Brian C. Lane wrote:
> On Sat, Nov 01, 2025 at 12:00:40AM +0100, Pascal Hambourg wrote:
>>
>> Indeed _parse_header updates entry_count, but then _disk_pop_update_mode
>> (which updates metadata and free space partitions) is called only if the
>> partition table has at least one active partition. Or later when a new
>> partition is created, or the pmbr_boot flag is set.
>
> Ah, ok. Now it's clear :) Thanks for that.
>
>> I quickly tested that surrounding the call to type->ops->read with
>> _disk_push_update_mode and _disk_pop_update_mode in ped_disk_new seems to
>> fix the issue:
(...)> This doesn't pass the tests -- gpt_read calls ped_disk_commit_to_dev
> when it needs to fix one of the headers, and that has an assert check on
> update_mode.
Oops, my poor knowledge of parted made me miss that.
> But, while it seems a bit like a kludge, I think we could just do a
> push/pop right after doing the read instead of wrapping it. That at
> least passes the tests and I don't think it would have any unexpected
> side-effects.
You know parted better and I cannot come with another suggestion. Want
me to submit the trivial patch ?
>> But I am now working on a larger patch which aims to stay in update mode and
>> avoid useless transient metadata and free space partition updates until
>> after reading the partition table.
Never mind, if type->ops->read must not be called while the disk is in
update mode then this approach cannot work.
Information forwarded
to
bug-parted <at> gnu.org:
bug#79720; Package
parted.
(Tue, 04 Nov 2025 19:33:02 GMT)
Full text and
rfc822 format available.
Message #20 received at 79720 <at> debbugs.gnu.org (full text, mbox):
On Tue, Nov 04, 2025 at 10:59:00AM +0100, Pascal Hambourg wrote:
> On 03/11/2025 à 22:45, Brian C. Lane wrote:
[snip]
> > But, while it seems a bit like a kludge, I think we could just do a
> > push/pop right after doing the read instead of wrapping it. That at
> > least passes the tests and I don't think it would have any unexpected
> > side-effects.
>
> You know parted better and I cannot come with another suggestion. Want me to
> submit the trivial patch ?
Sure! Send it to parted-devel <at> lists.alioth.debian.org so that it gets
more exposure.
Thanks,
Brian
--
Brian C. Lane (PST8PDT) - weldr.io - lorax - parted - pykickstart
This bug report was last modified 1 day ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.