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:
parent
089f9d795e
commit
8e2bca513e
2
part.h
2
part.h
|
@ -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];
|
||||
|
|
10
super-mbr.c
10
super-mbr.c
|
@ -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,
|
||||
|
@ -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)
|
||||
|
|
18
util.c
18
util.c
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue