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 | |
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')
-rw-r--r-- | sys/dev/pci/if_bnxt.c | 6 | ||||
-rw-r--r-- | sys/dev/pci/if_em.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_igc.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_ix.c | 10 | ||||
-rw-r--r-- | sys/dev/pci/if_ixl.c | 12 | ||||
-rw-r--r-- | sys/dev/pv/if_vio.c | 4 |
6 files changed, 21 insertions, 19 deletions
diff --git a/sys/dev/pci/if_bnxt.c b/sys/dev/pci/if_bnxt.c index 4771121e096..d6d79e9a3dc 100644 --- a/sys/dev/pci/if_bnxt.c +++ b/sys/dev/pci/if_bnxt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bnxt.c,v 1.45 2024/01/19 03:25:13 jmatthew Exp $ */ +/* $OpenBSD: if_bnxt.c,v 1.46 2024/02/13 13:58:19 bluhm Exp $ */ /*- * Broadcom NetXtreme-C/E network driver. * @@ -1433,13 +1433,13 @@ bnxt_start(struct ifqueue *ifq) lflags |= TX_BD_LONG_LFLAGS_LSO; hdrsize = sizeof(*ext.eh); if (ext.ip4) - hdrsize += ext.ip4->ip_hl << 2; + hdrsize += ext.ip4hlen; else if (ext.ip6) hdrsize += sizeof(*ext.ip6); else tcpstat_inc(tcps_outbadtso); - hdrsize += ext.tcp->th_off << 2; + hdrsize += ext.tcphlen; txhi->hdr_size = htole16(hdrsize / 2); outlen = m->m_pkthdr.ph_mss; diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c index 2c668af926c..18a4ce3f2e9 100644 --- a/sys/dev/pci/if_em.c +++ b/sys/dev/pci/if_em.c @@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE. ***************************************************************************/ -/* $OpenBSD: if_em.c,v 1.371 2024/01/28 18:42:58 mglocker Exp $ */ +/* $OpenBSD: if_em.c,v 1.372 2024/02/13 13:58:19 bluhm Exp $ */ /* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */ #include <dev/pci/if_em.h> @@ -2433,7 +2433,7 @@ em_tx_ctx_setup(struct em_queue *que, struct mbuf *mp, u_int head, vlan_macip_lens |= (sizeof(*ext.eh) << E1000_ADVTXD_MACLEN_SHIFT); if (ext.ip4) { - iphlen = ext.ip4->ip_hl << 2; + iphlen = ext.ip4hlen; type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { diff --git a/sys/dev/pci/if_igc.c b/sys/dev/pci/if_igc.c index 5deb53df970..952a9209efe 100644 --- a/sys/dev/pci/if_igc.c +++ b/sys/dev/pci/if_igc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_igc.c,v 1.15 2024/01/23 08:48:12 kevlo Exp $ */ +/* $OpenBSD: if_igc.c,v 1.16 2024/02/13 13:58:19 bluhm Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause * @@ -2028,7 +2028,7 @@ igc_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, int prod, ether_extract_headers(mp, &ext); if (ext.ip4) { - iphlen = ext.ip4->ip_hl << 2; + iphlen = ext.ip4hlen; type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV4; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { 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 { diff --git a/sys/dev/pci/if_ixl.c b/sys/dev/pci/if_ixl.c index 1f89dd73e87..153f3677d39 100644 --- a/sys/dev/pci/if_ixl.c +++ b/sys/dev/pci/if_ixl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ixl.c,v 1.95 2024/01/07 21:01:45 bluhm Exp $ */ +/* $OpenBSD: if_ixl.c,v 1.96 2024/02/13 13:58:19 bluhm Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -2827,7 +2827,7 @@ ixl_tx_setup_offload(struct mbuf *m0, struct ixl_tx_ring *txr, IXL_TX_DESC_CMD_IIPT_IPV4_CSUM : IXL_TX_DESC_CMD_IIPT_IPV4; - hlen = ext.ip4->ip_hl << 2; + hlen = ext.ip4hlen; #ifdef INET6 } else if (ext.ip6) { offload |= IXL_TX_DESC_CMD_IIPT_IPV6; @@ -2844,10 +2844,12 @@ ixl_tx_setup_offload(struct mbuf *m0, struct ixl_tx_ring *txr, if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; - offload |= (uint64_t)ext.tcp->th_off << IXL_TX_DESC_L4LEN_SHIFT; + offload |= (uint64_t)(ext.tcphlen >> 2) + << IXL_TX_DESC_L4LEN_SHIFT; } else if (ext.udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; - offload |= (sizeof(*ext.udp) >> 2) << IXL_TX_DESC_L4LEN_SHIFT; + offload |= (uint64_t)(sizeof(*ext.udp) >> 2) + << IXL_TX_DESC_L4LEN_SHIFT; } if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO)) { @@ -2855,7 +2857,7 @@ ixl_tx_setup_offload(struct mbuf *m0, struct ixl_tx_ring *txr, struct ixl_tx_desc *ring, *txd; uint64_t cmd = 0, paylen, outlen; - hlen += ext.tcp->th_off << 2; + hlen += ext.tcphlen; outlen = m0->m_pkthdr.ph_mss; paylen = m0->m_pkthdr.len - ETHER_HDR_LEN - hlen; diff --git a/sys/dev/pv/if_vio.c b/sys/dev/pv/if_vio.c index 550c4deb9f3..3648e4ac3f0 100644 --- a/sys/dev/pv/if_vio.c +++ b/sys/dev/pv/if_vio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vio.c,v 1.29 2023/12/20 09:51:06 jan Exp $ */ +/* $OpenBSD: if_vio.c,v 1.30 2024/02/13 13:58:19 bluhm Exp $ */ /* * Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg. @@ -765,7 +765,7 @@ again: hdr->csum_offset = offsetof(struct udphdr, uh_sum); if (ext.ip4) - hdr->csum_start += ext.ip4->ip_hl << 2; + hdr->csum_start += ext.ip4hlen; #ifdef INET6 else if (ext.ip6) hdr->csum_start += sizeof(*ext.ip6); |