Hello, I'm using iw 5.16 with Yocto kirkstone 4.0.13, kernel 6.1.55 on
SAM9G25 cpu.
When I execute `iw wlan0 scan` kernel report many Alignment traps, looks like:
Alignment trap: iw (6376) PC=0x00461ff8 Instr=0xe1f720b2
Address=0x0048e771 FSR 0x001
Alignment trap: iw (6376) PC=0x00461ff8 Instr=0xe1f720b2
Address=0x0048e773 FSR 0x001
Alignment trap: iw (6376) PC=0x004631c8 Instr=0xe1d420b0
Address=0x0048e771 FSR 0x001
Alignment trap: iw (6376) PC=0x00463190 Instr=0xe1d420b0
Address=0x0048e771 FSR 0x001
Upon investigation, they came from LDRH instructions inside __print_he_capa().
There are 2 callers, print_he_info() haven't issue as variables are
aligned in stack, but in print_he_capability() u16 variables are
directly casted from u8 without alignment check.
I tried a tentative fix which works but it's not clean enough to be
submitted as a patch:
---
util.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/util.c b/util.c
index 8a2ba10..941c6bf 100644
--- a/util.c
+++ b/util.c
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "iw.h"
#include "nl80211.h"
+#include <malloc.h>
void mac_addr_n2a(char *mac_addr, const unsigned char *arg)
{
@@ -1657,20 +1658,23 @@ void print_eht_info(struct nlattr *nl_iftype, int band)
void print_he_capability(const uint8_t *ie, int len)
{
- const void *mac_cap, *phy_cap, *mcs_set;
+ const __u16 mac_cap[3], phy_cap[6] = {0}, *mcs_set;
int mcs_len;
int i = 0;
- mac_cap = &ie[i];
+ memcpy(mac_cap, &ie[i], 6);
i += 6;
- phy_cap = &ie[i];
+ memcpy(phy_cap, &ie[i], 11);
i += 11;
- mcs_set = &ie[i];
mcs_len = len - i;
+ mcs_set = memalign(2, mcs_len);
+ memcpy(mcs_set, &ie[i], mcs_len);
__print_he_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false);
+
+ free(mcs_set);
}
void iw_hexdump(const char *prefix, const __u8 *buf, size_t size)
--
Thanks,
Zixun LI
On Fri, 2024-05-17 at 12:30 +0200, admin LI wrote:
> Hello, I'm using iw 5.16 with Yocto kirkstone 4.0.13, kernel 6.1.55 on
> SAM9G25 cpu.
>
> When I execute `iw wlan0 scan` kernel report many Alignment traps, looks like:
> Alignment trap: iw (6376) PC=0x00461ff8 Instr=0xe1f720b2
> Address=0x0048e771 FSR 0x001
> Alignment trap: iw (6376) PC=0x00461ff8 Instr=0xe1f720b2
> Address=0x0048e773 FSR 0x001
> Alignment trap: iw (6376) PC=0x004631c8 Instr=0xe1d420b0
> Address=0x0048e771 FSR 0x001
> Alignment trap: iw (6376) PC=0x00463190 Instr=0xe1d420b0
> Address=0x0048e771 FSR 0x001
>
Is that kind of thing not fixed up there? Does it even matter?
But I guess if we want to fix it, we'd really want something like
get_unaligned_le*() like in the kernel, not manually memcpy() in all the
code.
johannes