[Bug 283753] gpart: rejects MBR-formatted disks with partitions that include LBA 4294967295

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 30 Dec 2024 22:55:15 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283753

            Bug ID: 283753
           Summary: gpart: rejects MBR-formatted disks with partitions
                    that include LBA 4294967295
           Product: Base System
           Version: 15.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: asomers@FreeBSD.org

PROBLEM
=======
On a disk of 2TiB or more (0x100000000 512B sectors), gpart will wrongly reject
the partition table as corrupt if any partition's final LBA resides on the
0xffffffffth sector (sector 4294967295).  gpart will refuse to create any
device nodes, and print messages to dmesg like:

GEOM_PART: partition 4 has end offset beyond last LBA: 4294967295 > 4294967294
GEOM_PART: integrity check failed (md0, MBR)

STEPS TO REPRODUCE
==================
On GNU/Linux, do these commands
$ truncate -s 2199023255552 2t_file
$ /usr/sbin/fdisk almost_2t_file
At the interactive prompt, type these subcommands:
> o
> n
> p
> 1
> 
>
> p
Disk 2t_file: 2 TiB, 2199023255552 bytes, 4294967296 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x30b69544

Device     Boot Start        End    Sectors Size Id Type
2t_file1         2048 4294967295 4294965248   2T 83 Linux

Notice the end LBA of the partition is 4294967295.

Now, on FreeBSD, try to attach gpart to this file, like this:
$ sudo mdconfig -a -t vnode -f 2t_file
md0
$ gpart show md0
gpart: No such geom: md0.
$ dmesg | tail -n1
GEOM_PART: integrity check failed (md0, MBR)


IMPACT
======
GNU/Linux's fdisk tool (tested on Debian 12) will allow creating a partition
table with a primary partition that includes LBA 4294967295.  Attempting to
mount such a disk image on FreeBSD will fail with the above message.

This bug is unlikely to effect any physical hard disks, since none were ever
manufactured in 2 TiB capacities, and Linux refuses to allow a primary
partition that includes LBA 4294967296 or greater.  But it effects disk images
of 2 TiB, and disk images of greater than 2 TiB with a partition table that
only uses the first 2 TiB.

WORKAROUND
==========
Setting sysctl kern.geom.part.check_integrity=0 will workaround the problem. 
However, it will also disable other sanity checks that may be important.

ENVIRONMENT
===========
Tested on FreeBSD amd64 15.0-CURRENT as of 27-Dec-2024, and FreeBSD amd64
14.1-RELEASE.

ANALYSIS
========

An MBR partition entry contains a 32-bit field for each partition's starting
LBA and a 32-bit field for each partition's length in sectors.  So a partition
could theoretically start on LBA 0xffffffff and run for 0xffffffff sectors,
meaning that it's last LBA would be 0x1fffffffd.  But many (most?) tools reject
such partitions.  GNU/Linux, for example, will refuse to create a partition
that ends on a sector higher than 4294967295.  The logic in FreeBSD is found in
the g_part_check_integrity function, which requires the partition's last LBA to
be less than or equal to the disk's gpt_last value.

That gpt_last value is not recorded in the MBR; it's inferred from the disk's
mediasize.  In the function g_part_mbr_create it's set to "MIN(pp->mediasize /
pp->sectorsize, UINT32_MAX) - 1".  That code was added in SVN r221972 in May
2011 when gpart's MBR support was first added.  The older /sbin/fdisk tool did
not attempt such integrity validation.

I'm tempted to say that the logic in g_part_mbr_create is wrong, and the
correct expression should be "MIN(pp->mediasize / pp->sectorsize - 1,
UINT32_MAX)".  That would fix this bug.  However, I find similar expressions in
the code for other partition table formats: BSD, BSD64, APM, EBR, and even GPT.
 But not, however, LDM.  So I can't change it with confidence.

-- 
You are receiving this mail because:
You are the assignee for the bug.