Fix bus error when accessing MBR partition records

Since the MBR layout only has partition records as 2-byte aligned, the
32-bit fields in them are not aligned. Thus, they cannot be accessed on
some architectures (such as SPARC) by using a "struct MBR_part_record *"
pointer, as the compiler can assume that the pointer is properly aligned.
Instead, the records must be accessed by going through the MBR struct
itself every time.

Signed-off-by: James Clarke <jrtc27@jrtc27.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
James Clarke 2016-10-17 21:16:01 +01:00 committed by Jes Sorensen
parent 089f9d795e
commit 8e2bca513e
3 changed files with 22 additions and 8 deletions

2
part.h
View File

@ -40,7 +40,7 @@ struct MBR_part_record {
__u8 last_cyl; __u8 last_cyl;
__u32 first_sect_lba; __u32 first_sect_lba;
__u32 blocks_num; __u32 blocks_num;
}; } __attribute__((packed));
struct MBR { struct MBR {
__u8 pad[446]; __u8 pad[446];

View File

@ -57,6 +57,11 @@ static void examine_mbr(struct supertype *st, char *homehost)
printf(" MBR Magic : %04x\n", sb->magic); printf(" MBR Magic : %04x\n", sb->magic);
for (i = 0; i < MBR_PARTITIONS; i++) for (i = 0; i < MBR_PARTITIONS; i++)
/*
* Have to make every access through sb rather than using a
* pointer to the partition table (or an entry), since the
* entries are not properly aligned.
*/
if (sb->parts[i].blocks_num) if (sb->parts[i].blocks_num)
printf("Partition[%d] : %12lu sectors at %12lu (type %02x)\n", printf("Partition[%d] : %12lu sectors at %12lu (type %02x)\n",
i, i,
@ -151,6 +156,11 @@ static void getinfo_mbr(struct supertype *st, struct mdinfo *info, char *map)
info->component_size = 0; info->component_size = 0;
for (i = 0; i < MBR_PARTITIONS ; i++) for (i = 0; i < MBR_PARTITIONS ; i++)
/*
* Have to make every access through sb rather than using a
* pointer to the partition table (or an entry), since the
* entries are not properly aligned.
*/
if (sb->parts[i].blocks_num) { if (sb->parts[i].blocks_num) {
unsigned long last = unsigned long last =
(unsigned long)__le32_to_cpu(sb->parts[i].blocks_num) (unsigned long)__le32_to_cpu(sb->parts[i].blocks_num)

18
util.c
View File

@ -1412,7 +1412,6 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart)
static int get_last_partition_end(int fd, unsigned long long *endofpart) static int get_last_partition_end(int fd, unsigned long long *endofpart)
{ {
struct MBR boot_sect; struct MBR boot_sect;
struct MBR_part_record *part;
unsigned long long curr_part_end; unsigned long long curr_part_end;
unsigned part_nr; unsigned part_nr;
int retval = 0; int retval = 0;
@ -1429,21 +1428,26 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
if (boot_sect.magic == MBR_SIGNATURE_MAGIC) { if (boot_sect.magic == MBR_SIGNATURE_MAGIC) {
retval = 1; retval = 1;
/* found the correct signature */ /* found the correct signature */
part = boot_sect.parts;
for (part_nr = 0; part_nr < MBR_PARTITIONS; part_nr++) { for (part_nr = 0; part_nr < MBR_PARTITIONS; part_nr++) {
/*
* Have to make every access through boot_sect rather
* than using a pointer to the partition table (or an
* entry), since the entries are not properly aligned.
*/
/* check for GPT type */ /* check for GPT type */
if (part->part_type == MBR_GPT_PARTITION_TYPE) { if (boot_sect.parts[part_nr].part_type ==
MBR_GPT_PARTITION_TYPE) {
retval = get_gpt_last_partition_end(fd, endofpart); retval = get_gpt_last_partition_end(fd, endofpart);
break; break;
} }
/* check the last used lba for the current partition */ /* check the last used lba for the current partition */
curr_part_end = __le32_to_cpu(part->first_sect_lba) + curr_part_end =
__le32_to_cpu(part->blocks_num); __le32_to_cpu(boot_sect.parts[part_nr].first_sect_lba) +
__le32_to_cpu(boot_sect.parts[part_nr].blocks_num);
if (curr_part_end > *endofpart) if (curr_part_end > *endofpart)
*endofpart = curr_part_end; *endofpart = curr_part_end;
part++;
} }
} else { } else {
/* Unknown partition table */ /* Unknown partition table */