public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* rfc: test whether a device has a partition table
@ 2003-09-24 20:29 Andries.Brouwer
  2003-09-24 21:54 ` Linus Torvalds
  2003-09-25  0:42 ` Douglas Gilbert
  0 siblings, 2 replies; 19+ messages in thread
From: Andries.Brouwer @ 2003-09-24 20:29 UTC (permalink / raw)
  To: dougg, linux-kernel

As everyone knows it is a bad idea to let the kernel guess
whether there is a partition table on a given block device,
and if so, of what type.
Nevertheless this is what almost everybody does.

Until now the philosophy was: floppies do not have a partition table,
disks do have one, and for ZIP drives nobody knows. With USB we get
more types of block device that may or may not have a partition table
(and if they have none, usually there is a FAT filesystem with bootsector).
In such cases the kernel assumes a partition table, and creates a mess
if there was none. Some heuristics are needed.

Many checks are possible (for a DOS-type partition table: boot indicator
must be 0 or 0x80, partitions are not larger than the disk,
non-extended partitions are mutually disjoint; for a boot sector:
it starts with a jump, the number of bytes per sector is 512 or
at least a power of two, the number of sectors per cluster is 1
or at least a power of two, the number of reserved sectors is 1 or 32,
the number of FAT copies is 2, ...).

I tried a minimal test, and the below is good enough for the
boot sectors and DOS-type partition tables that I have here.

So, question: are there people with DOS-type partition tables
or FAT fs bootsectors where the below gives the wrong answer?
I would be interested in a copy of the sector.

I expect to submit some sanity check to DOS-type partition table
parsing, and hope to recognize with high probability the presence
of a full disk FAT filesystem.

Andries

------------ sniffsect.c -----------------

/*
 * Given a block device, does it have a DOS-type partition table?
 * Or does it behave like a floppy and have a whole-disk filesystem?
 * Or is it something else?
 *
 * Return 1 for pt, -1 for boot sect, 0 for unknown.
 */

#include <stdio.h>
#include <fcntl.h>

/* DOS-type partition */
struct partition {
	unsigned char bootable;             /* 0 or 0x80 */
	unsigned char begin_chs[3];
	unsigned char systype;
	unsigned char end_chs[3];
	unsigned char start_sect[4];
	unsigned char nr_sects[4];
};

int sniffsect(unsigned char *p) {
	struct partition *pt;
	int i, n;
	int maybept = 1;
	int maybebs = 1;

	/* Both DOS-type pt and boot sector have a 55 aa signature */
	if (p[510] != 0x55 || p[511] != 0xaa)
		return 0;

	/* A partition table has boot indicators 0 or 0x80 */
	for (i=0; i<4; i++) {
		pt = (struct partition *)(p + 446 + 16*i);
		if (pt->bootable != 0 && pt->bootable != 0x80)
			maybept = 0;
	}

	/* A boot sector has a power of two as #sectors/cluster */
	n = p[13];
	if (n == 0 || (n & (n-1)) != 0)
		maybebs = 0;

	/* A boot sector has a power of two as #bytes/sector */
	n = (p[12] << 8) + p[11];
	if (n == 0 || (n & (n-1)) != 0)
		maybebs = 0;

	return maybept - maybebs;
}

int main(int argc, char **argv) {
	unsigned char sect[512];
	int fd, n;

	if (argc != 2) {
		fprintf(stderr, "Call: sniffsect file\n");
		exit(1);
	}

	fd = open(argv[1], O_RDONLY);
	if (fd == -1) {
		perror(argv[1]);
		fprintf(stderr, "Cannot open %s\n", argv[1]);
		exit(1);
	}

	n = read(fd, sect, sizeof(sect));
	if (n != sizeof(sect)) {
		if (n == -1)
			perror(argv[1]);
		fprintf(stderr, "Cannot read 512 bytes from %s\n", argv[1]);
		exit(1);
	}

	n = sniffsect(sect);
	printf((n == 1) ? "partition table\n" :
	       (n == -1) ? "boot sector\n" : "no idea\n");
	return 0;
}

^ permalink raw reply	[flat|nested] 19+ messages in thread
* Re: rfc: test whether a device has a partition table
@ 2004-05-22 11:18 Uwe Bonnes
  2004-05-22 12:37 ` John Bradford
  2004-05-22 12:56 ` Andries Brouwer
  0 siblings, 2 replies; 19+ messages in thread
From: Uwe Bonnes @ 2004-05-22 11:18 UTC (permalink / raw)
  To: linux-kernel; +Cc: Andries.Brouwer

Hello,

around last september there was a discussion about the linux kernel
recognizing "supperfloppys" as disks with bogus partition tables.
Linux Torvalds wrote at one point in the discussion:
>On Thu, 25 Sep 2003, Andries Brouwer wrote:
>> 
>> My post implicitly suggested the minimal thing to do.
>> It will not be enough - heuristics are never enough -
>> but it probably helps in most cases.
>
>I don't mind the 0x00/0x80 "boot flag" checks - those look fairly 
> obvious and look reasonably safe to add to the partitioning code.
>
>There are other checks that can be done - verifying that the start/end
>sector values are at all sensible. We do _some_ of that, but only for
>partitions 3 and 4, for example. We could do more - like checking the
>actual sector numbers (but I think some formatters leave them as zero).
>
>Which actually makes me really nervous - it implies that we've probably 
>seen partitions 1&2 contain garbage there, and the problem is that if 
>you'r etoo careful in checking, you will make a system unusable.
>
>This is why it is so much nicer to be overly permissive ratehr than 
>being a stickler for having all the values right.
>
>And your random byte checks for power-of-2 make no sense. What are they
>based on?

The discussion seemed to fade out with no visible result, and for example my
USB stick "ID 0d7d:1420 Apacer" with a floppy as second partition gets
recognized as:
SCSI device sdc: 2880 512-byte hdwr sectors (1 MB)
sdc: Write Protect is off
 sdc: sdc1 sdc2 sdc3 sdc4

Find appended a patch that does the 0x00/0x80 "boot flag" checks. Please
discuss and consider for inclusion into the kernel.

Thanks

PS: CC me for faster reaction, as I only follow the mailing list via the
MARC mailing list archive.
-- 
Uwe Bonnes                bon@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
--- linux-2.6.6/fs/partitions/msdos-sav.c	2004-05-10 04:32:52.000000000 +0200
+++ linux-2.6.6/fs/partitions/msdos.c	2004-05-22 12:54:45.000000000 +0200
@@ -32,6 +32,7 @@
  */
 #include <asm/unaligned.h>
 
+#define BOOT_IND(p)	(get_unaligned(&p->boot_ind))
 #define SYS_IND(p)	(get_unaligned(&p->sys_ind))
 #define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
 				get_unaligned(&p->nr_sects);	\
@@ -377,6 +378,7 @@
 int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
 	int sector_size = bdev_hardsect_size(bdev) / 512;
+	int nr_bootable = 0;
 	Sector sect;
 	unsigned char *data;
 	struct partition *p;
@@ -389,6 +391,22 @@
 		put_dev_sector(sect);
 		return 0;
 	}
+
+	/* 
+	   Some consistancy check for a valid partition table
+	   Boot indicator must either be 0x80 or 0x0 on all primary partitions
+	   Only one partition may be marked bootable (0x80)
+	*/
+ 	p = (struct partition *) (data + 0x1be);
+	for (slot = 1 ; slot <= 4 ; slot++, p++) {
+	  if ( (BOOT_IND(p) != 0x80) && (BOOT_IND(p) != 0x0))
+	    return 0;
+	  if (BOOT_IND(p) == 0x80) 
+	    nr_bootable++;
+	}
+	if (nr_bootable >1) 
+	  return 0;
+
 	p = (struct partition *) (data + 0x1be);
 #ifdef CONFIG_EFI_PARTITION
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2004-05-22 15:14 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-09-24 20:29 rfc: test whether a device has a partition table Andries.Brouwer
2003-09-24 21:54 ` Linus Torvalds
2003-09-24 23:50   ` Andries Brouwer
2003-09-25  0:05     ` viro
2003-09-25 12:14       ` Andries Brouwer
2003-09-25  0:18     ` Linus Torvalds
2003-09-25  6:53       ` Xavier Bestel
2003-09-25 10:57       ` Andries Brouwer
2003-09-25  4:47     ` Linus Torvalds
2003-09-25  4:56       ` Linus Torvalds
2003-09-25 11:42       ` Andries Brouwer
2003-10-05  9:00   ` Meelis Roos
2003-09-25  0:42 ` Douglas Gilbert
2003-09-25  1:00   ` viro
2003-09-25  1:27     ` Douglas Gilbert
  -- strict thread matches above, loose matches on Subject: below --
2004-05-22 11:18 Uwe Bonnes
2004-05-22 12:37 ` John Bradford
2004-05-22 12:56 ` Andries Brouwer
2004-05-22 15:14   ` Uwe Bonnes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox