diff options
author | Jim Meyering <meyering@redhat.com> | 2008-01-10 14:51:56 +0100 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2008-02-04 08:21:49 +0100 |
commit | 71bbe2995371357c534dccf1eb3d436b399eaf32 (patch) | |
tree | 9da52c00ca2418dc1eff3586ca229ddde593c89a /libparted/disk.c | |
parent | f564981d2e5f4d5daad5a6f704dfa22ffaa9cf94 (diff) | |
download | parted-71bbe2995371357c534dccf1eb3d436b399eaf32.tar.gz |
Enforce inherent limitations of dos and dvh partition table formats.
* libparted/disk.c (_check_partition): Enforce the 32-bit limitation
on a partition's starting sector number and length (in sectors).
With the usual 512-byte sector size, this limits the maximum
partition size to just under 2TB.
(_partition_max_start, _partition_max_len): New functions.
(_check_partition): Use them.
* tests/t4100-msdos-partition-limits.sh: New file. Test vs. msdos.
* tests/t4100-dvh-partition-limits.sh: New file. Test vs. dvh.
* tests/Makefile.am (TESTS): Add t4100-msdos-partition-limits.sh
and t4100-dvh-partition-limits.sh.
Diffstat (limited to 'libparted/disk.c')
-rw-r--r-- | libparted/disk.c | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/libparted/disk.c b/libparted/disk.c index 087fbbf..ec09996 100644 --- a/libparted/disk.c +++ b/libparted/disk.c @@ -1,6 +1,6 @@ /* libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2007 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -38,6 +38,7 @@ #include <parted/debug.h> #include "architecture.h" +#include "intprops.h" #if ENABLE_NLS # include <libintl.h> @@ -1695,6 +1696,31 @@ _check_extended_partition (PedDisk* disk, PedPartition* part) return 1; } +static PedSector +_partition_max_start (char const *label_type) +{ + /* List partition table names (a la disk->type->name) for which + the partition length, in sectors, must fit in 32 bytes. */ + static char const *const max_32[] = {"msdos", "dvh"}; + unsigned int i; + + for (i = 0; i < sizeof max_32 / sizeof *max_32; i++) + if (strcmp (label_type, max_32[i]) == 0) + return UINT32_MAX; + + return TYPE_MAXIMUM (PedSector); +} + +static PedSector +_partition_max_len (char const *label_type) +{ + /* NOTE: for now, they happen to be the same, so don't + duplicate needlessly. Of course, if there's some format + with different length and starting sector limits, then + these functions will diverge. */ + return _partition_max_start (label_type); +} + static int _check_partition (PedDisk* disk, PedPartition* part) { @@ -1735,6 +1761,45 @@ _check_partition (PedDisk* disk, PedPartition* part) return 0; } + if (!(part->type & PED_PARTITION_METADATA)) { + char const *label_type = disk->type->name; + /* Enforce some restrictions inherent in the DOS + partition table format. Without these, one would be able + to create a 2TB partition (or larger), and it would work, + but only until the next reboot. This was insidious: the + too-large partition would work initially, because with + Linux-2.4.x and newer we set the partition start sector + and length (in sectors) accurately and directly via the + BLKPG ioctl. However, only the last 32 bits of each + number would be written to the partition table, and the + next time the system would read/use those corrupted numbers + it would usually complain about an invalid partition. + The same applies to the starting sector number. */ + + if (part->geom.length > _partition_max_len (label_type)) { + ped_exception_throw ( + PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("partition length of %jd sectors exceeds the " + "%s-partition-table-imposed maximum of %jd"), + part->geom.length, + label_type, + _partition_max_len (label_type)); + return 0; + } + + /* The starting sector number must fit in 32 bytes. */ + if (part->geom.start > _partition_max_start (label_type)) { + ped_exception_throw ( + PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("starting sector number, %jd exceeds the" + " %s-partition-table-imposed maximum of %jd"), + part->geom.start, + label_type, + _partition_max_start (label_type)); + return 0; + } + } + return 1; } |