diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-02-13 13:58:20 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2024-02-13 13:58:20 +0000 |
commit | 3bf939b5dc77522812f021796d66a014be458f59 (patch) | |
tree | 5e98564ecc20b96ac4acd5523b1e56a519165e5d /sys/dev/pci/if_ix.c | |
parent | 7d3d1aab4b11f9c8e07a3078344f27e6176b86aa (diff) |
Analyse header layout in ether_extract_headers().
Several drivers need IPv4 header length and TCP offset for checksum
offload, TSO and LRO. Accessing these fields directly caused crashes
on sparc64 due to misaligned access. It cannot be guaranteed that
IP and TCP header is 4 byte aligned in driver level. Also gcc 4.2.1
assumes that bit fields can be accessed with 32 bit load instructions.
Use memcpy() in ether_extract_headers() to get the bits from IPv4
and TCP header and store the header length in struct ether_extracted.
From there network drivers can esily use it without caring about
alignment and bit shift. Do some sanity checks with the length
values to prevent that invalid values from evil packets get stored
into hardware registers. If check fails, clear the pointer to the
header to hide it from the driver. Add debug prints that help to
figure out the reason for bad packets and provide information when
debugging drivers.
OK mglocker@
Diffstat (limited to 'sys/dev/pci/if_ix.c')
-rw-r--r-- | sys/dev/pci/if_ix.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 9b838f49e34..87a6bfef88d 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.c,v 1.206 2023/11/10 15:51:20 bluhm Exp $ */ +/* $OpenBSD: if_ix.c,v 1.207 2024/02/13 13:58:19 bluhm Exp $ */ /****************************************************************************** @@ -2502,7 +2502,7 @@ ixgbe_tx_offload(struct mbuf *mp, uint32_t *vlan_macip_lens, *vlan_macip_lens |= (ethlen << IXGBE_ADVTXD_MACLEN_SHIFT); if (ext.ip4) { - iphlen = ext.ip4->ip_hl << 2; + iphlen = ext.ip4hlen; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8; @@ -2542,7 +2542,7 @@ ixgbe_tx_offload(struct mbuf *mp, uint32_t *vlan_macip_lens, if (ext.tcp) { uint32_t hdrlen, thlen, paylen, outlen; - thlen = ext.tcp->th_off << 2; + thlen = ext.tcphlen; outlen = mp->m_pkthdr.ph_mss; *mss_l4len_idx |= outlen << IXGBE_ADVTXD_MSS_SHIFT; @@ -3277,11 +3277,11 @@ ixgbe_rxeof(struct rx_ring *rxr) hdrlen += ETHER_VLAN_ENCAP_LEN; #endif if (ext.ip4) - hdrlen += ext.ip4->ip_hl << 2; + hdrlen += ext.ip4hlen; if (ext.ip6) hdrlen += sizeof(*ext.ip6); if (ext.tcp) { - hdrlen += ext.tcp->th_off << 2; + hdrlen += ext.tcphlen; tcpstat_inc(tcps_inhwlro); tcpstat_add(tcps_inpktlro, pkts); } else { |