On Thu, Jan 13, 2022 at 12:43:57PM -0700, Theo de Raadt wrote: > > - m_getptr() returns the correct mbuf and offset to the header. I > > think we can assume that a single IPv6 header, that our stack has > > created, is in contiguous memory. The IPv4 case just above makes > > the same assumption. > > And if the assumption is not met due to interations between various > tunnel or encapsulation layers... then panic the kernel? That is OK?
It was OK for IPv4 during more than 6 years. 1.118 (mikeb 20-Mar-15): m = m_getptr(mp, ehdrlen, &ipoff); 1.118 (mikeb 20-Mar-15): KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip)); 1.118 (mikeb 20-Mar-15): ip = (struct ip *)(m->m_data + ipoff); But to be safe we can use a combination of simple access in the hot path and m_copydata() in rare cases. Untested and IPv4-only. If you like it, Jan can do it with IPv6 tomorrow. bluhm Index: dev/pci/if_ix.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ix.c,v retrieving revision 1.180 diff -u -p -r1.180 if_ix.c --- dev/pci/if_ix.c 27 Jul 2021 01:44:55 -0000 1.180 +++ dev/pci/if_ix.c 13 Jan 2022 20:14:33 -0000 @@ -2437,12 +2437,9 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, #else struct ether_header *eh; #endif - struct ip *ip; #ifdef notyet struct ip6_hdr *ip6; #endif - struct mbuf *m; - int ipoff; uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0; int ehdrlen, ip_hlen = 0; uint16_t etype; @@ -2511,16 +2508,23 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT; switch (etype) { - case ETHERTYPE_IP: + case ETHERTYPE_IP: { + struct ip *ip, ipdata; + if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip)) return (-1); - m = m_getptr(mp, ehdrlen, &ipoff); - KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip)); - ip = (struct ip *)(m->m_data + ipoff); + if ((mtod(mp, unsigned long) & ALIGNBYTES) == 0 && + mp->m_len >= ehdrlen + sizeof(*ip)) { + ip = (struct ip *)(mp->m_data + ehdrlen); + } else { + m_copydata(mp, ehdrlen, sizeof(ipdata), &ipdata); + ip = &ipdata; + } ip_hlen = ip->ip_hl << 2; ipproto = ip->ip_p; type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; break; + } #ifdef notyet case ETHERTYPE_IPV6: if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip6))