Red Hat Bugzilla – Bug 1344482
util-linux fails valid_pmbr() size checks if device is > 2.14TB, Device label type: dos instead of gpt
Last modified: 2016-11-03 17:27:27 EDT
Description of problem: In using fdisk against disks with GUID/GPT partitioning, expecting to see Command (m for help): p Disk /dev/sde: 3298.5 GB, 3298534883328 bytes, 6442450944 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 33550336 bytes Disk label type: gpt Disk identifier: 0x00000000 ...and will when the disk is <2.14TB (so technically wouldn't need to use GUID/GPT partitioning). but when disks are >2.14TB in size, it displays instead: Command (m for help): p Disk /dev/sde: 3298.5 GB, 3298534883328 bytes, 6442450944 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 33550336 bytes Disk label type: dos <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Disk identifier: 0x000000000 Version-Release number of selected component (if applicable): util-linux-2.23.2-26.el7_2.2 How reproducible: 100% Steps to Reproduce: 1. parted /dev/sdX mklabel gpt 2. fdisk -uc /dev/sdX 3. Actual results: Disk label type: dos Expected results: Disk label type: gpt Additional info: /* * Protective MBRs take up the lesser of the whole disk * or 2 TiB (32bit LBA), ignoring the rest of the disk. * * Hybrid MBRs do not necessarily comply with this. */ if (ret == GPT_MBR_PROTECTIVE) { if (le32_to_cpu(pmbr->partition_record[0].size_in_lba) != min((uint32_t) cxt->total_sectors - 1, 0xFFFFFFFF)) ret = 0; } Will compute result in ret=0 when disk is > 2.14TB. For example, a 3TB disk has total sectors of 0x180000000, min() function above ends up as: min( 0x80000000-1, 0xFFFFFFFF ) min( 0x7FFFFFFF , 0xFFFFFFFF ) = 0x7FFFFFFF Disks > 2.14TB will have the size_in_lba limited to 0xFFFFFFFF (UINT_MAX), resulting in the above if ... statement being true and ret=0 is returned when it shouldn't be. The correct code would be something like: (uint32_t)min( cxt->total_sectors - 1, 0xFFFFFFFFULL ) The above min() as above is used in both valid_pmbr() and gpt_mknew_pmbr(), possibly others. Current code essentially looks like it computes: (total_sectors-1) & 0xFFFFFFFF vs comparing total_sectors-1 to UINT_MAX and then truncating the results of the comparison. Note that while physical disks are often in whole TiB size, provisioned disks in storage can be odd sizes like total_sectors = 0500005C00 which would end up with a reported min of 0x00005BFF with the current code.
Created attachment 1166630 [details] gpt check patch attached patch tested, resulted in expected output: fdisk w/attached patch: # fdisk -uc /dev/sde WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion. <<<<<<<<<<<<<<<<[1] Welcome to fdisk (util-linux 2.23.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/sde: 3298.5 GB, 3298534883328 bytes, 6442450944 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 33550336 bytes Disk label type: gpt <<<<<<<<<<<<<<<< [2] # Start End Size Type Name <<<<<< [3] [1] is output at end of gpt_label_probe(), so it detects GUID/GPT correctly [2] and displays gpt [3] and currently this gpt table is empty [just did parted mklabel on disk]
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://rhn.redhat.com/errata/RHSA-2016-2605.html