summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-02-13 13:58:20 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-02-13 13:58:20 +0000
commit3bf939b5dc77522812f021796d66a014be458f59 (patch)
tree5e98564ecc20b96ac4acd5523b1e56a519165e5d /sys/dev
parent7d3d1aab4b11f9c8e07a3078344f27e6176b86aa (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.c6
-rw-r--r--sys/dev/pci/if_em.c4
-rw-r--r--sys/dev/pci/if_igc.c4
-rw-r--r--sys/dev/pci/if_ix.c10
-rw-r--r--sys/dev/pci/if_ixl.c12
-rw-r--r--sys/dev/pv/if_vio.c4
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);