diff --git a/usr.sbin/bhyve/pci_e82545.c b/usr.sbin/bhyve/pci_e82545.c --- a/usr.sbin/bhyve/pci_e82545.c +++ b/usr.sbin/bhyve/pci_e82545.c @@ -233,7 +233,7 @@ * Debug printf */ static int e82545_debug = 0; -#define WPRINTF(msg,params...) PRINTLN("e82545: " msg, params) +#define WPRINTF(msg,params...) PRINTLN("e82545: " msg, ##params) #define DPRINTF(msg,params...) if (e82545_debug) WPRINTF(msg, params) #define MIN(a,b) (((a)<(b))?(a):(b)) @@ -1086,15 +1086,18 @@ union e1000_tx_udesc *dsc; int desc, dtype, len, ntype, iovcnt, tcp, tso; int mss, paylen, seg, tiovcnt, left, now, nleft, nnow, pv, pvoff; - unsigned hdrlen, vlen; + unsigned hdrlen, vlen, pktlen; uint32_t tcpsum, tcpseq; uint16_t ipcs, tcpcs, ipid, ohead; + bool invalid; ckinfo[0].ck_valid = ckinfo[1].ck_valid = 0; iovcnt = 0; ntype = 0; tso = 0; + pktlen = 0; ohead = head; + invalid = false; /* iovb[0/1] may be used for writable copy of headers. */ iov = &iovb[2]; @@ -1144,17 +1147,23 @@ len = (dtype == E1000_TXD_TYP_L) ? dsc->td.lower.flags.length : dsc->dd.lower.data & 0xFFFFF; - if (len > 0) { - /* Strip checksum supplied by guest. */ - if ((dsc->td.lower.data & E1000_TXD_CMD_EOP) != 0 && - (dsc->td.lower.data & E1000_TXD_CMD_IFCS) == 0) + /* Strip checksum supplied by guest. */ + if ((dsc->td.lower.data & E1000_TXD_CMD_EOP) != 0 && + (dsc->td.lower.data & E1000_TXD_CMD_IFCS) == 0) { + if (len <= 2) { + WPRINTF("final descriptor too short (%d) -- dropped", + len); + invalid = true; + } else len -= 2; - if (iovcnt < I82545_MAX_TXSEGS) { - iov[iovcnt].iov_base = paddr_guest2host( - sc->esc_ctx, dsc->td.buffer_addr, len); - iov[iovcnt].iov_len = len; - } + } + + if (len > 0 && iovcnt < I82545_MAX_TXSEGS) { + iov[iovcnt].iov_base = paddr_guest2host(sc->esc_ctx, + dsc->td.buffer_addr, len); + iov[iovcnt].iov_len = len; iovcnt++; + pktlen += len; } /* @@ -1202,6 +1211,9 @@ } } + if (invalid) + goto done; + if (iovcnt > I82545_MAX_TXSEGS) { WPRINTF("tx too many descriptors (%d > %d) -- dropped", iovcnt, I82545_MAX_TXSEGS); @@ -1295,8 +1307,13 @@ } } + if (pktlen < hdrlen + vlen) { + WPRINTF("packet too small for writable header"); + goto done; + } + /* Allocate, fill and prepend writable header vector. */ - if (hdrlen != 0) { + if (hdrlen + vlen != 0) { hdr = __builtin_alloca(hdrlen + vlen); hdr += vlen; for (left = hdrlen, hdrp = hdr; left > 0;