From 1e44c52a69d3c94528c3239b137bf9d009056523 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 22 Nov 2010 22:33:55 +0000 Subject: [PATCH 1/5] * partmap/msdos.c (embed_signatures): New array. (pc_partition_map_embed): Check for and avoid sectors matching any of the signatures in embed_signatures. * util/grub-setup.c (setup): Allow for the embedding area being split into multiple blocklists. --- ChangeLog.embed-sectors | 7 ++++ grub-core/partmap/msdos.c | 84 ++++++++++++++++++++++++++++++++++++++- util/grub-setup.c | 13 +++--- 3 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 ChangeLog.embed-sectors diff --git a/ChangeLog.embed-sectors b/ChangeLog.embed-sectors new file mode 100644 index 000000000..e9eade480 --- /dev/null +++ b/ChangeLog.embed-sectors @@ -0,0 +1,7 @@ +2010-11-22 Colin Watson + + * partmap/msdos.c (embed_signatures): New array. + (pc_partition_map_embed): Check for and avoid sectors matching any + of the signatures in embed_signatures. + * util/grub-setup.c (setup): Allow for the embedding area being + split into multiple blocklists. diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index f99e27a6e..cb836d171 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -27,6 +27,45 @@ static struct grub_partition_map grub_msdos_partition_map; +#ifdef GRUB_UTIL +#include + +struct embed_signature +{ + const char *name; + const char *signature; + int signature_len; +}; + +/* Signatures of other software that may be using sectors in the embedding + area. */ +struct embed_signature embed_signatures[] = + { + { + .name = "ZISD", + .signature = "ZISD", + .signature_len = 4 + }, + { + .name = "FlexNet", + .signature = "\xd4\x41\xa0\xf5\x03\x00\x03\x00", + .signature_len = 8 + }, + { + .name = "FlexNet", + .signature = "\xd8\x41\xa0\xf5\x02\x00\x02\x00", + .signature_len = 8 + }, + { + /* from Ryan Perkins */ + .name = "HP Backup and Recovery Manager (?)", + .signature = "\x70\x8a\x5d\x46\x35\xc5\x1b\x93" + "\xae\x3d\x86\xfd\xb1\x55\x3e\xe0", + .signature_len = 16 + } + }; +#endif + grub_err_t grub_partition_msdos_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, @@ -234,13 +273,56 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, if (end >= *nsectors + 1) { - int i; + int i, j; + char *embed_signature_check; + unsigned int orig_nsectors, extra_sectors = 0; + + orig_nsectors = *nsectors; *nsectors = end - 1; *sectors = grub_malloc (*nsectors * sizeof (**sectors)); if (!*sectors) return grub_errno; for (i = 0; i < *nsectors; i++) (*sectors)[i] = 1 + i; + + /* Check for software that is already using parts of the embedding + * area. + */ + embed_signature_check = grub_malloc (GRUB_DISK_SECTOR_SIZE); + for (i = 0; i < *nsectors; i++) + { + if (grub_disk_read (disk, (*sectors)[i], 0, GRUB_DISK_SECTOR_SIZE, + embed_signature_check)) + continue; + + for (j = 0; j < ARRAY_SIZE (embed_signatures); j++) + if (! grub_memcmp (embed_signatures[j].signature, + embed_signature_check, + embed_signatures[j].signature_len)) + break; + if (j == ARRAY_SIZE (embed_signatures)) + continue; + grub_util_warn ("Sector %llu is already in use by %s; avoiding it. " + "This software may cause boot or other problems in " + "future. Please ask its authors not to store data " + "in the boot track", + (*sectors)[i], embed_signatures[j].name); + extra_sectors++; + + /* Avoid this sector. */ + for (j = i; j < *nsectors; j++) + (*sectors)[j]++; + } + grub_free (embed_signature_check); + + if (end + extra_sectors < orig_nsectors + 1) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Other software is using the embedding area, and " + "there is not enough room for core.img. Such " + "software is often trying to store data in a way " + "that avoids detection. We recommend you " + "investigate."); + return GRUB_ERR_NONE; } diff --git a/util/grub-setup.c b/util/grub-setup.c index fa95f94aa..e0c1db8ca 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -442,6 +442,13 @@ setup (const char *dir, save_blocklists (sectors[i] + grub_partition_get_start (container), 0, GRUB_DISK_SECTOR_SIZE); + /* Make sure that the last blocklist is a terminator. */ + if (block == first_block) + block--; + block->start = 0; + block->len = 0; + block->segment = 0; + write_rootdev (core_img, root_dev, boot_img, first_sector); core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); @@ -458,12 +465,6 @@ setup (const char *dir, nsec * GRUB_DISK_SECTOR_SIZE - core_size); - /* Make sure that the second blocklist is a terminator. */ - block = first_block - 1; - block->start = 0; - block->len = 0; - block->segment = 0; - /* Write the core image onto the disk. */ for (i = 0; i < nsec; i++) grub_disk_write (dest_dev->disk, sectors[i], 0, From 5de124b3541d1239c30f0315632cfa214c2ef9f8 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 14 Mar 2011 21:41:24 +0000 Subject: [PATCH 2/5] Avoid straying into first partition when embedding-area sectors are in use (LP: #730225). --- grub-core/partmap/msdos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index cb836d171..c6340a231 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -275,7 +275,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, { int i, j; char *embed_signature_check; - unsigned int orig_nsectors, extra_sectors = 0; + unsigned int orig_nsectors; orig_nsectors = *nsectors; *nsectors = end - 1; @@ -307,7 +307,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, "future. Please ask its authors not to store data " "in the boot track", (*sectors)[i], embed_signatures[j].name); - extra_sectors++; + (*nsectors)--; /* Avoid this sector. */ for (j = i; j < *nsectors; j++) @@ -315,7 +315,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, } grub_free (embed_signature_check); - if (end + extra_sectors < orig_nsectors + 1) + if (*nsectors < orig_nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, "Other software is using the embedding area, and " "there is not enough room for core.img. Such " From 6f4b2814bf2e3d531718dbca19559b43056e3322 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 14 Mar 2011 21:42:00 +0000 Subject: [PATCH 3/5] update paths in ChangeLog --- ChangeLog.embed-sectors | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.embed-sectors b/ChangeLog.embed-sectors index e9eade480..b1d5868e7 100644 --- a/ChangeLog.embed-sectors +++ b/ChangeLog.embed-sectors @@ -1,6 +1,6 @@ -2010-11-22 Colin Watson +2011-03-14 Colin Watson - * partmap/msdos.c (embed_signatures): New array. + * grub-core/partmap/msdos.c (embed_signatures): New array. (pc_partition_map_embed): Check for and avoid sectors matching any of the signatures in embed_signatures. * util/grub-setup.c (setup): Allow for the embedding area being From 58ed62d2214c7bf1ab23aa991806540926016773 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 25 Mar 2011 17:22:12 +0000 Subject: [PATCH 4/5] Avoid consuming lots of space and time if the first partition is not near the start of the disk (Debian bug #619458, Ubuntu bug #691569). --- ChangeLog.embed-sectors | 9 +++++++-- grub-core/partmap/gpt.c | 3 +++ grub-core/partmap/msdos.c | 17 +++++++++++++++-- include/grub/partition.h | 1 + util/grub-setup.c | 4 +--- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ChangeLog.embed-sectors b/ChangeLog.embed-sectors index b1d5868e7..a8de67d24 100644 --- a/ChangeLog.embed-sectors +++ b/ChangeLog.embed-sectors @@ -1,7 +1,12 @@ 2011-03-14 Colin Watson + * include/grub/partition.h (grub_partition_map): Change prototype of + embed to take a maximum value for nsectors. * grub-core/partmap/msdos.c (embed_signatures): New array. (pc_partition_map_embed): Check for and avoid sectors matching any - of the signatures in embed_signatures. + of the signatures in embed_signatures, up to max_nsectors. + * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restrict + returned sector map to max_nsectors. * util/grub-setup.c (setup): Allow for the embedding area being - split into multiple blocklists. + split into multiple blocklists. Tell dest_partmap->embed the + maximum number of sectors we care about. diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 7f2c36143..c4c10d73d 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -125,6 +125,7 @@ gpt_partition_map_iterate (grub_disk_t disk, #ifdef GRUB_UTIL static grub_err_t gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + unsigned int max_nsectors, grub_embed_type_t embed_type, grub_disk_addr_t **sectors) { @@ -174,6 +175,8 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, " embedding won't be possible!"); *nsectors = len; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; *sectors = grub_malloc (*nsectors * sizeof (**sectors)); if (!*sectors) return grub_errno; diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index acfa6f302..0352d6949 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -185,6 +185,7 @@ grub_partition_msdos_iterate (grub_disk_t disk, #ifdef GRUB_UTIL static grub_err_t pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, + unsigned int max_nsectors, grub_embed_type_t embed_type, grub_disk_addr_t **sectors) { @@ -275,10 +276,13 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, { unsigned i, j; char *embed_signature_check; - unsigned int orig_nsectors; + unsigned int orig_nsectors, avail_nsectors; orig_nsectors = *nsectors; *nsectors = end - 2; + avail_nsectors = *nsectors; + if (*nsectors > max_nsectors) + *nsectors = max_nsectors; *sectors = grub_malloc (*nsectors * sizeof (**sectors)); if (!*sectors) return grub_errno; @@ -307,11 +311,20 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, "future. Please ask its authors not to store data " "in the boot track", (*sectors)[i], embed_signatures[j].name); - (*nsectors)--; + avail_nsectors--; + if (avail_nsectors < *nsectors) + *nsectors = avail_nsectors; /* Avoid this sector. */ for (j = i; j < *nsectors; j++) (*sectors)[j]++; + + /* Have we run out of space? */ + if (avail_nsectors < orig_nsectors) + break; + + /* Make sure to check the next sector. */ + i--; } grub_free (embed_signature_check); diff --git a/include/grub/partition.h b/include/grub/partition.h index e7e00ef7f..13ada8614 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -49,6 +49,7 @@ struct grub_partition_map #ifdef GRUB_UTIL /* Determine sectors available for embedding. */ grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors, + unsigned int max_nsectors, grub_embed_type_t embed_type, grub_disk_addr_t **sectors); #endif diff --git a/util/grub-setup.c b/util/grub-setup.c index dc2ab0cce..02abb0d1f 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -426,10 +426,8 @@ setup (const char *dir, } nsec = core_sectors; - err = dest_partmap->embed (dest_dev->disk, &nsec, + err = dest_partmap->embed (dest_dev->disk, &nsec, 2 * core_sectors, GRUB_EMBED_PCBIOS, §ors); - if (nsec > 2 * core_sectors) - nsec = 2 * core_sectors; if (err) { From af0ce67056482b9c7b6a8aeaecc6a004283f3be5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 3 Apr 2011 23:52:50 +0200 Subject: [PATCH 5/5] Add HighPoint RAID controller --- grub-core/partmap/msdos.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 0352d6949..55545646b 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -35,8 +35,19 @@ struct embed_signature const char *name; const char *signature; int signature_len; + enum { TYPE_SOFTWARE, TYPE_RAID } type; }; +const char message_warn[][200] = { + [TYPE_RAID] = "Sector %llu is already in use by %s; avoiding it. " + "Please ask the manufacturer not to store data in MBR gap", + [TYPE_SOFTWARE] = "Sector %llu is already in use by %s; avoiding it. " + "This software may cause boot or other problems in " + "future. Please ask its authors not to store data " + "in the boot track" +}; + + /* Signatures of other software that may be using sectors in the embedding area. */ struct embed_signature embed_signatures[] = @@ -44,24 +55,34 @@ struct embed_signature embed_signatures[] = { .name = "ZISD", .signature = "ZISD", - .signature_len = 4 + .signature_len = 4, + .type = TYPE_SOFTWARE }, { .name = "FlexNet", .signature = "\xd4\x41\xa0\xf5\x03\x00\x03\x00", - .signature_len = 8 + .signature_len = 8, + .type = TYPE_SOFTWARE }, { .name = "FlexNet", .signature = "\xd8\x41\xa0\xf5\x02\x00\x02\x00", - .signature_len = 8 + .signature_len = 8, + .type = TYPE_SOFTWARE }, { /* from Ryan Perkins */ .name = "HP Backup and Recovery Manager (?)", .signature = "\x70\x8a\x5d\x46\x35\xc5\x1b\x93" "\xae\x3d\x86\xfd\xb1\x55\x3e\xe0", - .signature_len = 16 + .signature_len = 16, + .type = TYPE_SOFTWARE + }, + { + .name = "HighPoint RAID controller", + .signature = "ycgl", + .signature_len = 4, + .type = TYPE_RAID } }; #endif @@ -306,10 +327,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, break; if (j == ARRAY_SIZE (embed_signatures)) continue; - grub_util_warn ("Sector %llu is already in use by %s; avoiding it. " - "This software may cause boot or other problems in " - "future. Please ask its authors not to store data " - "in the boot track", + grub_util_warn (message_warn[embed_signatures[j].type], (*sectors)[i], embed_signatures[j].name); avail_nsectors--; if (avail_nsectors < *nsectors)