diff options
author | marcel <marcel@FreeBSD.org> | 2006-06-04 20:26:13 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2006-06-04 20:26:13 +0000 |
commit | 00649b114383cedc1e28dfa1cdd9b4c5f4b2a496 (patch) | |
tree | 24d93c1256a582b507a89a51b4ea209613eeba7d | |
parent | 501751fbc7b2af470f10aeec5b6c1bfaa56d9ea2 (diff) | |
download | FreeBSD-src-00649b114383cedc1e28dfa1cdd9b4c5f4b2a496.zip FreeBSD-src-00649b114383cedc1e28dfa1cdd9b4c5f4b2a496.tar.gz |
Fix unaligned memory accesses on Alpha and possible other platforms.
By using a pointer to struct dos_partition, we implicitly tell the
compiler that the pointer is 4-bytes aligned, even though we know
that's not the case. The fact that we only dereference the pointer
to access a byte-wide field (field dp_ptyp) is not a guarantee that
the compiler will in fact use a byte-wide load. On some platforms
it's more efficient to use long word or quad word loads and use
bit-shifting and bit-masking to get the intended byte. On those
platforms an misaligned load will be the result.
The fix is to use byte-wide pointer arithmetic based on sizeof() and
offsetof() to avoid invalid casts which avoids that the compiler
makes invalid assumptions.
Backtrace provided by: wilko@
MFC after: 1 week
-rw-r--r-- | sys/geom/geom_gpt.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/sys/geom/geom_gpt.c b/sys/geom/geom_gpt.c index 8e5b583..aa074ee 100644 --- a/sys/geom/geom_gpt.c +++ b/sys/geom/geom_gpt.c @@ -358,8 +358,8 @@ g_gpt_ctl_remove(struct gctl_req *req, const char *flags, struct g_geom *gp, static int g_gpt_has_pmbr(struct g_consumer *cp, int *error) { - struct dos_partition *part; char *buf; + uint8_t *typ; int i, pmbr; uint16_t magic; @@ -373,9 +373,10 @@ g_gpt_has_pmbr(struct g_consumer *cp, int *error) if (magic != DOSMAGIC) goto out; - part = (struct dos_partition *)(uintptr_t)(buf + DOSPARTOFF); for (i = 0; i < 4; i++) { - if (part[i].dp_typ != 0 && part[i].dp_typ != DOSPTYP_PMBR) + typ = buf + DOSPARTOFF + i * sizeof(struct dos_partition) + + offsetof(struct dos_partition, dp_typ); + if (*typ != 0 && *typ != DOSPTYP_PMBR) goto out; } |