wlantest: Avoid unaligned iphdr pointers

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>
This commit is contained in:
Brian Norris 2021-02-12 19:03:35 -08:00 committed by Jouni Malinen
parent 35756c02ea
commit 1e537a2756

View file

@ -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 *dst, const u8 *src, const u8 *data, size_t len,
const u8 *peer_addr) const u8 *peer_addr)
{ {
const struct ip *ip; struct ip ip;
const u8 *payload; const u8 *payload;
size_t plen; size_t plen;
uint16_t frag_off, ip_len; uint16_t frag_off, ip_len;
ip = (const struct ip *) data; if (len < sizeof(ip))
if (len < sizeof(*ip))
return; return;
if (ip->ip_v != 4) { os_memcpy(&ip, data, sizeof(ip));
if (ip.ip_v != 4) {
if (hwsim_test_packet(data, len)) { if (hwsim_test_packet(data, len)) {
add_note(wt, MSG_INFO, "hwsim_test package"); add_note(wt, MSG_INFO, "hwsim_test package");
return; return;
} }
add_note(wt, MSG_DEBUG, "Unexpected IP protocol version %u in " add_note(wt, MSG_DEBUG, "Unexpected IP protocol version %u in "
"IPv4 packet (bssid=" MACSTR " str=" MACSTR "IPv4 packet (bssid=" MACSTR " str=" MACSTR
" dst=" MACSTR ")", ip->ip_v, MAC2STR(bssid), " dst=" MACSTR ")", ip.ip_v, MAC2STR(bssid),
MAC2STR(src), MAC2STR(dst)); MAC2STR(src), MAC2STR(dst));
return; 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 " add_note(wt, MSG_DEBUG, "Unexpected IP header length %u in "
"IPv4 packet (bssid=" MACSTR " str=" MACSTR "IPv4 packet (bssid=" MACSTR " str=" MACSTR
" dst=" MACSTR ")", ip->ip_hl, MAC2STR(bssid), " dst=" MACSTR ")", ip.ip_hl, MAC2STR(bssid),
MAC2STR(src), MAC2STR(dst)); MAC2STR(src), MAC2STR(dst));
return; 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) " add_note(wt, MSG_DEBUG, "Truncated IP header (ihl=%u len=%u) "
"in IPv4 packet (bssid=" MACSTR " str=" MACSTR "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)); MAC2STR(bssid), MAC2STR(src), MAC2STR(dst));
return; 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) { if (frag_off & 0x1fff) {
wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet " wpa_printf(MSG_EXCESSIVE, "IP fragment reassembly not yet "
"supported"); "supported");
return; return;
} }
ip_len = be_to_host16(ip->ip_len); ip_len = be_to_host16(ip.ip_len);
if (ip_len > len) if (ip_len > len)
return; return;
if (ip_len < len) if (ip_len < len)
len = ip_len; len = ip_len;
payload = data + 4 * ip->ip_hl; payload = data + 4 * ip.ip_hl;
plen = len - 4 * ip->ip_hl; plen = len - 4 * ip.ip_hl;
switch (ip->ip_p) { switch (ip.ip_p) {
#ifndef __APPLE__ #ifndef __APPLE__
case IPPROTO_ICMP: case IPPROTO_ICMP:
rx_data_icmp(wt, bssid, sta_addr, ip->ip_dst.s_addr, rx_data_icmp(wt, bssid, sta_addr, ip.ip_dst.s_addr,
ip->ip_src.s_addr, payload, plen, peer_addr); ip.ip_src.s_addr, payload, plen, peer_addr);
break; break;
#endif /* __APPLE__ */ #endif /* __APPLE__ */
} }