summaryrefslogtreecommitdiff
path: root/libparted/disk.c
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2008-01-10 14:51:56 +0100
committerJim Meyering <meyering@redhat.com>2008-02-04 08:21:49 +0100
commit71bbe2995371357c534dccf1eb3d436b399eaf32 (patch)
tree9da52c00ca2418dc1eff3586ca229ddde593c89a /libparted/disk.c
parentf564981d2e5f4d5daad5a6f704dfa22ffaa9cf94 (diff)
downloadparted-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.c67
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;
}