Skip to content

Commit

Permalink
Fix bus error when accessing MBR partition records
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Jes Sorensen <[email protected]>
  • Loading branch information
jrtc27 authored and Jes Sorensen committed Oct 19, 2016
1 parent 089f9d7 commit 8e2bca5
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
2 changes: 1 addition & 1 deletion part.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct MBR_part_record {
__u8 last_cyl;
__u32 first_sect_lba;
__u32 blocks_num;
};
} __attribute__((packed));

struct MBR {
__u8 pad[446];
Expand Down
10 changes: 10 additions & 0 deletions super-mbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ static void examine_mbr(struct supertype *st, char *homehost)

printf(" MBR Magic : %04x\n", sb->magic);
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)
printf("Partition[%d] : %12lu sectors at %12lu (type %02x)\n",
i,
Expand Down Expand Up @@ -151,6 +156,11 @@ static void getinfo_mbr(struct supertype *st, struct mdinfo *info, char *map)
info->component_size = 0;

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) {
unsigned long last =
(unsigned long)__le32_to_cpu(sb->parts[i].blocks_num)
Expand Down
18 changes: 11 additions & 7 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct MBR boot_sect;
struct MBR_part_record *part;
unsigned long long curr_part_end;
unsigned part_nr;
int retval = 0;
Expand All @@ -1429,21 +1428,26 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
if (boot_sect.magic == MBR_SIGNATURE_MAGIC) {
retval = 1;
/* found the correct signature */
part = boot_sect.parts;

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 */
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);
break;
}
/* check the last used lba for the current partition */
curr_part_end = __le32_to_cpu(part->first_sect_lba) +
__le32_to_cpu(part->blocks_num);
curr_part_end =
__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)
*endofpart = curr_part_end;

part++;
}
} else {
/* Unknown partition table */
Expand Down

0 comments on commit 8e2bca5

Please sign in to comment.