Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tool to adjust partition tables when sector size changes
This includes a C program that adjusts partition tables when the device sector size changes. It is intended to be secure against malicious inputs, although it will not be used with untrusted inputs in Qubes OS. In particular, all calculations are done with sufficiently wide integer types to prevent overflow or wraparound, partition tables read from disk are strictly validated before use, and the total size of the partition table entries is limited to 1MiB. The partition table adjustment does not change the start or end of any partition. If the old sector size is 512 and the new size is 4096, the tool will return an error if any partition does not start or end on a 4096-byte boundary. Furthermore, this tool will refuse to write a partition table if either the primary or backup GPT would overwrite data that is part of any partition. This ensures that user data is not corrupted. All used entries in the original GPT are preserved. However, unused entries will be truncated if necessary. The FirstUsableLBA and LastUsableLBA fields are converted if necessary, and are rounded in the direction of _less_ usable space. This means that FirstUsableLBA is rounded up, while LastUsableLBA is rounded down. If the new primary GPT uses space after FirstUsableLBA, or the new backup GPT uses space before LastUsableLBA, the values of these fields are adjusted accordingly. The new partition tables are written in a crash-safe way. This ensures that in the event of a system crash or power loss, there is always a valid GPT that can be used. The specific algorithm used is as follows: 1. If the GPT being written is the primary GPT, start by writing the pMBR, followed by (new sector size - 512) bytes of zeroes. 2. If the new sector size is 512, overwrite the old 512-byte-sector GPT header with zeroes, then overwrite the old 4096-byte-sector GPT header with zeroes. 3. Write the partition entries. 4. Write the new partition header. All writes are made with O_SYNC, so they cannot be reordered on-disk. Furthermore, overwriting a single sector is atomic. If the primary GPT was valid, the backup GPT is written first; otherwise, the primary GPT is written first. The default CFLAGS enable sanitizers and are intended for local development only. Production builds should set CFLAGS via the 'make' command line or an environment variable, which will override the CFLAGS in the Makefile. The tool will exit with a failure status if file descriptor 0, 1, or 2 is closed when it is invoked. Using these FDs could potentially cause the device to get clobbered or read from accidentally, which would be bad. The block device is opened exclusively to prevent racing with other code that will use the device. It is fsync()d before being used to ensure that the code operates on the most recent on-disk state, not on stale state cached in memory. The whole block device is locked exclusively to avoid racing with udev. If the user passes a partition, the tool exits with an error. A BIOS Parameter Block (BPB) is checked for, to avoid accidentally corrupting a FAT or NTFS file system that happens to have a GPT with valid checksums at the wrong location.
- Loading branch information