3
3
sectors matching any of the signatures in embed_signatures.
4
4
Author: Colin Watson <cjwatson@ubuntu.com>
5
5
Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-08/msg00137.html
6
Last-Update: 2010-09-17
6
Last-Update: 2010-11-22
8
Index: b/util/i386/pc/grub-setup.c
9
===================================================================
10
--- a/util/i386/pc/grub-setup.c
11
+++ b/util/i386/pc/grub-setup.c
13
#define grub_host_to_target32(x) grub_cpu_to_le32(x)
14
#define grub_host_to_target64(x) grub_cpu_to_le64(x)
8
Index: b/ChangeLog.embed-sectors
9
===================================================================
11
+++ b/ChangeLog.embed-sectors
13
+2010-11-22 Colin Watson <cjwatson@ubuntu.com>
15
+ * partmap/msdos.c (embed_signatures): New array.
16
+ (pc_partition_map_embed): Check for and avoid sectors matching any
17
+ of the signatures in embed_signatures.
18
+ * util/grub-setup.c (setup): Allow for the embedding area being
19
+ split into multiple blocklists.
20
Index: b/grub-core/partmap/msdos.c
21
===================================================================
22
--- a/grub-core/partmap/msdos.c
23
+++ b/grub-core/partmap/msdos.c
25
static struct grub_partition_map grub_msdos_partition_map;
29
+#include <grub/emu/misc.h>
16
31
+struct embed_signature
18
33
+ const char *name;
45
60
+ .signature = "\x70\x8a\x5d\x46\x35\xc5\x1b\x93"
46
61
+ "\xae\x3d\x86\xfd\xb1\x55\x3e\xe0",
47
62
+ .signature_len = 16
50
+ .name = "Dell DataSafe Local Backup",
51
+ .signature = "\xf6\x14\x84\xb4\xc1\x13\x01\xf5",
57
grub_xputs_real (const char *str)
63
- grub_disk_addr_t first_sector;
64
+ grub_disk_addr_t first_sector, es;
65
grub_uint16_t current_segment
66
= GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4);
67
grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE;
69
assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG
70
+ (GRUB_DISK_SECTOR_SIZE >> 4)));
68
grub_partition_msdos_iterate (grub_disk_t disk,
69
int (*hook) (grub_disk_t disk,
72
- /* Make sure that the second blocklist is a terminator. */
73
block = first_block - 1;
75
+ if (strcmp (dest_partmap, "msdos") == 0)
77
+ /* Check for software that is already using parts of the MBR gap. */
78
+ char *embed_signature_check = xmalloc (GRUB_DISK_SECTOR_SIZE);
79
+ grub_uint16_t extra_sectors = 0;
81
+ for (es = embed_region.start + 1; es < embed_region.start + core_sectors;
72
if (end >= *nsectors + 1)
76
+ char *embed_signature_check;
77
+ unsigned int orig_nsectors, extra_sectors = 0;
79
+ orig_nsectors = *nsectors;
81
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
84
for (i = 0; i < *nsectors; i++)
85
(*sectors)[i] = 1 + i;
87
+ /* Check for software that is already using parts of the embedding
90
+ embed_signature_check = grub_malloc (GRUB_DISK_SECTOR_SIZE);
91
+ for (i = 0; i < *nsectors; i++)
84
+ struct grub_boot_blocklist *prev_block;
85
+ grub_uint64_t prev_start;
86
+ grub_uint16_t prev_len;
87
+ grub_uint16_t prev_segment;
89
+ if (grub_disk_read (dest_dev->disk, es, 0, GRUB_DISK_SECTOR_SIZE,
93
+ if (grub_disk_read (disk, (*sectors)[i], 0, GRUB_DISK_SECTOR_SIZE,
90
94
+ embed_signature_check))
93
+ for (i = 0; i < ARRAY_SIZE (embed_signatures); i++)
94
+ if (! memcmp (embed_signatures[i].signature, embed_signature_check,
95
+ embed_signatures[i].signature_len))
97
+ for (j = 0; j < ARRAY_SIZE (embed_signatures); j++)
98
+ if (! grub_memcmp (embed_signatures[j].signature,
99
+ embed_signature_check,
100
+ embed_signatures[j].signature_len))
97
+ if (i == ARRAY_SIZE (embed_signatures))
102
+ if (j == ARRAY_SIZE (embed_signatures))
99
+ 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.",
100
+ es, embed_signatures[i].name);
104
+ grub_util_warn ("Sector %llu is already in use by %s; avoiding it. "
105
+ "This software may cause boot or other problems in "
106
+ "future. Please ask its authors not to store data "
107
+ "in the boot track",
108
+ (*sectors)[i], embed_signatures[j].name);
101
109
+ extra_sectors++;
103
+ /* Adjust the last blocklist, splitting it in two if necessary, to
104
+ avoid this sector. */
105
+ prev_block = block + 1;
106
+ prev_start = grub_target_to_host64 (prev_block->start);
107
+ prev_len = grub_target_to_host16 (prev_block->len);
108
+ prev_segment = grub_target_to_host16 (prev_block->segment);
110
+ if (es == prev_start)
111
+ prev_block->start = grub_host_to_target64 (prev_start + 1);
114
+ prev_block->len = grub_host_to_target16 (es - prev_start);
116
+ block->start = grub_host_to_target64 (es + 1);
117
+ block->len = grub_host_to_target16
118
+ (prev_len - (es - prev_start));
119
+ block->segment = grub_host_to_target16
121
+ (GRUB_DISK_SECTOR_SIZE >> 4) * (es - prev_start));
125
+ grub_util_error (_("the post-MBR gap is too fragmented by sectors used by other software"));
128
+ free (embed_signature_check);
130
+ if ((unsigned long) (core_sectors + extra_sectors)
131
+ > embed_region.end - embed_region.start)
133
+ grub_util_warn (_("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."));
134
+ goto unable_to_embed;
138
+ /* Make sure that the last blocklist is a terminator. */
143
/* Write the core image onto the disk. */
144
- if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img))
145
+ if (grub_disk_write (dest_dev->disk, embed_region.start, 0,
146
+ GRUB_DISK_SECTOR_SIZE, core_img))
147
grub_util_error ("%s", grub_errmsg);
148
+ tmp_img = core_img + GRUB_DISK_SECTOR_SIZE;
149
+ for (block = first_block; block->start; block--)
151
+ grub_uint64_t start;
154
+ start = grub_target_to_host64 (block->start);
155
+ size = grub_target_to_host16 (block->len) << GRUB_DISK_SECTOR_BITS;
156
+ /* The last sector may be incomplete. */
157
+ if (! (block + 1)->start && (core_size % GRUB_DISK_SECTOR_SIZE))
158
+ size -= GRUB_DISK_SECTOR_SIZE - (core_size % GRUB_DISK_SECTOR_SIZE);
160
+ if (grub_disk_write (dest_dev->disk, start, 0, size, tmp_img))
161
+ grub_util_error ("%s", grub_errmsg);
165
/* FIXME: can this be skipped? */
111
+ /* Avoid this sector. */
112
+ for (j = i; j < *nsectors; j++)
115
+ grub_free (embed_signature_check);
117
+ if (end + extra_sectors < orig_nsectors + 1)
118
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
119
+ "Other software is using the embedding area, and "
120
+ "there is not enough room for core.img. Such "
121
+ "software is often trying to store data in a way "
122
+ "that avoids detection. We recommend you "
125
return GRUB_ERR_NONE;
128
Index: b/util/grub-setup.c
129
===================================================================
130
--- a/util/grub-setup.c
131
+++ b/util/grub-setup.c
133
save_blocklists (sectors[i] + grub_partition_get_start (container),
134
0, GRUB_DISK_SECTOR_SIZE);
136
+ /* Make sure that the last blocklist is a terminator. */
137
+ if (block == first_block)
141
+ block->segment = 0;
143
write_rootdev (core_img, root_dev, boot_img, first_sector);
145
core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE);
147
nsec * GRUB_DISK_SECTOR_SIZE
150
- /* Make sure that the second blocklist is a terminator. */
151
- block = first_block - 1;
154
- block->segment = 0;
156
/* Write the core image onto the disk. */
157
for (i = 0; i < nsec; i++)
158
grub_disk_write (dest_dev->disk, sectors[i], 0,