diff mbox series

wlantest: avoid unaligned iphdr pointers

Message ID 20210213030335.777799-1-briannorris@chromium.org
State Accepted
Headers show
Series wlantest: avoid unaligned iphdr pointers | expand

Commit Message

Brian Norris Feb. 13, 2021, 3:03 a.m. UTC
Buffers passed to rx_data_ip() may not be naturally-aligned, and so we
get unpredictable behavior when we cast that to an IP header. In
particular, this code may crash on ARM.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
We have have the same problem in ICMP code, but I haven't hit such a
crash yet.

 wlantest/rx_ip.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

Comments

Jouni Malinen Feb. 13, 2021, 10:53 p.m. UTC | #1
On Fri, Feb 12, 2021 at 07:03:35PM -0800, Brian Norris wrote:
> Buffers passed to rx_data_ip() may not be naturally-aligned, and so we
> get unpredictable behavior when we cast that to an IP header. In
> particular, this code may crash on ARM.

Thanks, applied.
diff mbox series

Patch

diff --git a/wlantest/rx_ip.c b/wlantest/rx_ip.c
index fdf80b7d77a1..00ee544a18de 100644
--- a/wlantest/rx_ip.c
+++ b/wlantest/rx_ip.c
@@ -120,63 +120,64 @@  void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr,
 		const u8 *dst, const u8 *src, const u8 *data, size_t len,
 		const u8 *peer_addr)
 {
-	const struct ip *ip;
+	struct ip ip;
 	const u8 *payload;
 	size_t plen;
 	uint16_t frag_off, ip_len;
 
-	ip = (const struct ip *) data;
-	if (len < sizeof(*ip))
+	if (len < sizeof(ip))
 		return;
-	if (ip->ip_v != 4) {
+	memcpy(&ip, data, sizeof(ip));
+
+	if (ip.ip_v != 4) {
 		if (hwsim_test_packet(data, len)) {
 			add_note(wt, MSG_INFO, "hwsim_test package");
 			return;
 		}
 		add_note(wt, MSG_DEBUG, "Unexpected IP protocol version %u in "
 			 "IPv4 packet (bssid=" MACSTR " str=" MACSTR
-			 " dst=" MACSTR ")", ip->ip_v, MAC2STR(bssid),
+			 " dst=" MACSTR ")", ip.ip_v, MAC2STR(bssid),
 			 MAC2STR(src), MAC2STR(dst));
 		return;
 	}
-	if (ip->ip_hl * 4 < sizeof(*ip)) {
+	if (ip.ip_hl * 4 < sizeof(ip)) {
 		add_note(wt, MSG_DEBUG, "Unexpected IP header length %u in "
 			 "IPv4 packet (bssid=" MACSTR " str=" MACSTR
-			 " dst=" MACSTR ")", ip->ip_hl, MAC2STR(bssid),
+			 " dst=" MACSTR ")", ip.ip_hl, MAC2STR(bssid),
 			 MAC2STR(src), MAC2STR(dst));
 		return;
 	}
-	if (ip->ip_hl * 4 > len) {
+	if (ip.ip_hl * 4 > len) {
 		add_note(wt, MSG_DEBUG, "Truncated IP header (ihl=%u len=%u) "
 			 "in IPv4 packet (bssid=" MACSTR " str=" MACSTR
-			 " dst=" MACSTR ")", ip->ip_hl, (unsigned) len,
+			 " dst=" MACSTR ")", ip.ip_hl, (unsigned) len,
 			 MAC2STR(bssid), MAC2STR(src), MAC2STR(dst));
 		return;
 	}
 
-	/* TODO: check header checksum in ip->ip_sum */
+	/* TODO: check header checksum in ip.ip_sum */
 
-	frag_off = be_to_host16(ip->ip_off);
+	frag_off = be_to_host16(ip.ip_off);
 	if (frag_off & 0x1fff) {
 		wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet "
 			   "supported");
 		return;
 	}
 
-	ip_len = be_to_host16(ip->ip_len);
+	ip_len = be_to_host16(ip.ip_len);
 	if (ip_len > len)
 		return;
 	if (ip_len < len)
 		len = ip_len;
 
-	payload = data + 4 * ip->ip_hl;
-	plen = len - 4 * ip->ip_hl;
+	payload = data + 4 * ip.ip_hl;
+	plen = len - 4 * ip.ip_hl;
 
-	switch (ip->ip_p) {
+	switch (ip.ip_p) {
 #ifndef __APPLE__
 	case IPPROTO_ICMP:
-		rx_data_icmp(wt, bssid, sta_addr, ip->ip_dst.s_addr,
-			     ip->ip_src.s_addr, payload, plen, peer_addr);
+		rx_data_icmp(wt, bssid, sta_addr, ip.ip_dst.s_addr,
+			     ip.ip_src.s_addr, payload, plen, peer_addr);
 		break;
 #endif /* __APPLE__ */
 	}