summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2015-03-20 10:41:16 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2015-03-20 10:41:16 +0000
commitc1dfca4bc32d96d4ae0c01ac57ddc82c65289642 (patch)
treef20879279fc4c1ea6a774ee76aa2eab864fffb18 /sys
parent477cf2c45b4f87e43500e8d612d09b3865f2524b (diff)
Re-apply -r1.115 that got accidentally reverted and brought to my
attention and fix re-tested by Kapetanakis Giannis. Thanks a lot! Original commit message: When setting up advanced TX descriptor use m_getptr to locate the IP or IPv6 header instead of assuming contiguousness of the target buffer across Ethernet and IP/IPv6 headers. Tested by Kapetanakis Giannis <bilias at edu ! physics ! uoc ! gr>, thanks! Problem analysis and initial diff by dlg@.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_ix.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c
index 042bd6c6a6f..a05c836f9f4 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.117 2015/02/12 04:58:59 dlg Exp $ */
+/* $OpenBSD: if_ix.c,v 1.118 2015/03/20 10:41:15 mikeb Exp $ */
/******************************************************************************
@@ -2049,6 +2049,8 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
#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;
@@ -2094,9 +2096,13 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
* Jump over vlan headers if already present,
* helpful for QinQ too.
*/
+ if (mp->m_len < sizeof(struct ether_header))
+ return (1);
#if NVLAN > 0
eh = mtod(mp, struct ether_vlan_header *);
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ if (mp->m_len < sizeof(struct ether_vlan_header))
+ return (1);
etype = ntohs(eh->evl_proto);
ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
} else {
@@ -2114,15 +2120,23 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
switch (etype) {
case ETHERTYPE_IP:
- ip = (struct ip *)(mp->m_data + ehdrlen);
+ 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);
ip_hlen = ip->ip_hl << 2;
ipproto = ip->ip_p;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
break;
#ifdef notyet
case ETHERTYPE_IPV6:
- ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen);
- ip_hlen = sizeof(struct ip6_hdr);
+ if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip6))
+ return (1);
+ m = m_getptr(mp, ehdrlen, &ipoff);
+ KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip6));
+ ip6 = (struct ip6 *)(m->m_data + ipoff);
+ ip_hlen = sizeof(*ip6);
/* XXX-BZ this will go badly in case of ext hdrs. */
ipproto = ip6->ip6_nxt;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;