Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 May 2023 21:28:51 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: c5e433b99ed3 - main - stand: Avoid unaligned access in smbios code
Message-ID:  <202305012128.341LSpEB085938@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=c5e433b99ed3ddef0eb4fa937f38c34d4a3c4ae0

commit c5e433b99ed3ddef0eb4fa937f38c34d4a3c4ae0
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2023-05-01 21:12:34 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2023-05-01 21:12:34 +0000

    stand: Avoid unaligned access in smbios code
    
    This code was written on x86 where unaligned accesses were
    easy. LinuxBoot running on aarch64 uses mmap of /dev/mem to read the
    smbios table. Linux's mapping of this memory doesn't allow the normal
    unaligned fixup, so we get a bus error instead. We can't use the more
    natural le16dec and friends because they optimize into a single,
    unaligned memory load. We don't see this issue on aarch64 UEFI because
    memory is mapped such that unaligned accesses are fixed up.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D39793
---
 stand/libsa/smbios.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 42 insertions(+), 5 deletions(-)

diff --git a/stand/libsa/smbios.c b/stand/libsa/smbios.c
index 657e1635e6e1..a88d3ac4ab69 100644
--- a/stand/libsa/smbios.c
+++ b/stand/libsa/smbios.c
@@ -96,10 +96,47 @@ __FBSDID("$FreeBSD$");
 #define	SMBIOS3_SIG		"_SM3_"
 #define	SMBIOS_DMI_SIG		"_DMI_"
 
-#define	SMBIOS_GET8(base, off)	(*(uint8_t *)((base) + (off)))
-#define	SMBIOS_GET16(base, off)	(*(uint16_t *)((base) + (off)))
-#define	SMBIOS_GET32(base, off)	(*(uint32_t *)((base) + (off)))
-#define	SMBIOS_GET64(base, off)	(*(uint64_t *)((base) + (off)))
+/*
+ * 5.1 General
+ *...
+ * NOTE The Entry Point Structure and all SMBIOS structures assume a
+ * little-endian ordering convention...
+ * ...
+ *
+ * We use memcpy to avoid unaligned access to memory. To normal memory, this is
+ * fine, but the memory we are using might be mmap'd /dev/mem which under Linux
+ * on aarch64 doesn't allow unaligned access. leXdec and friends can't be used
+ * because those can optimize to an unaligned load (which often is fine, but not
+ * for mmap'd /dev/mem which has special memory attributes).
+ */
+static inline uint8_t SMBIOS_GET8(const caddr_t base, int off) { return (base[off]); }
+
+static inline uint16_t
+SMBIOS_GET16(const caddr_t base, int off)
+{
+	uint16_t v;
+
+	memcpy(&v, base + off, sizeof(v));
+	return (le16toh(v));
+}
+
+static inline uint32_t
+SMBIOS_GET32(const caddr_t base, int off)
+{
+	uint32_t v;
+
+	memcpy(&v, base + off, sizeof(v));
+	return (le32toh(v));
+}
+
+static inline uint64_t
+SMBIOS_GET64(const caddr_t base, int off)
+{
+	uint64_t v;
+
+	memcpy(&v, base + off, sizeof(v));
+	return (le64toh(v));
+}
 
 #define	SMBIOS_GETLEN(base)	SMBIOS_GET8(base, 0x01)
 #define	SMBIOS_GETSTR(base)	((base) + SMBIOS_GETLEN(base))
@@ -195,7 +232,7 @@ smbios_setenv(const char *name, caddr_t addr, const int offset)
 #define	UUID_TYPE		uint32_t
 #define	UUID_STEP		sizeof(UUID_TYPE)
 #define	UUID_ALL_BITS		(UUID_SIZE / UUID_STEP)
-#define	UUID_GET(base, off)	(*(UUID_TYPE *)((base) + (off)))
+#define	UUID_GET(base, off)	SMBIOS_GET32(base, off)
 
 static void
 smbios_setuuid(const char *name, const caddr_t addr, const int ver __unused)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305012128.341LSpEB085938>