summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/i86pc/io/viona/viona.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/usr/src/uts/i86pc/io/viona/viona.c b/usr/src/uts/i86pc/io/viona/viona.c
index 5fd5ddb5ea..4ae0f7317f 100644
--- a/usr/src/uts/i86pc/io/viona/viona.c
+++ b/usr/src/uts/i86pc/io/viona/viona.c
@@ -2532,9 +2532,18 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr,
ipha_t *ipha = NULL;
uint8_t ipproto = IPPROTO_NONE; /* NONE is not exactly right, but ok */
uint16_t flags = 0;
+ const uint_t csum_start = hdr->vrh_csum_start;
+ const uint_t csum_stuff = hdr->vrh_csum_offset + csum_start;
- if (MBLKL(mp) < sizeof (*eth)) {
- /* Buffers shorter than an ethernet header are hopeless */
+ /*
+ * Validate that the checksum offsets provided by the guest are within
+ * the bounds of the packet. Additionally, ensure that the checksum
+ * contents field is within the headers mblk copied by viona_tx().
+ */
+ if (csum_start >= len || csum_start < eth_len || csum_stuff >= len ||
+ (csum_stuff + sizeof (uint16_t)) > MBLKL(mp)) {
+ VIONA_PROBE2(fail_hcksum, viona_link_t *, link, mblk_t *, mp);
+ VIONA_RING_STAT_INCR(ring, fail_hcksum);
return (B_FALSE);
}
@@ -2634,17 +2643,13 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr,
*/
if ((link->l_cap_csum & HCKSUM_INET_PARTIAL) != 0 &&
(ipproto == IPPROTO_TCP || ipproto == IPPROTO_UDP)) {
- uint_t start, stuff, end;
-
/*
* MAC expects these offsets to be relative to the
* start of the L3 header rather than the L2 frame.
*/
- start = hdr->vrh_csum_start - eth_len;
- stuff = start + hdr->vrh_csum_offset;
- end = len - eth_len;
flags |= HCK_PARTIALCKSUM;
- mac_hcksum_set(mp, start, stuff, end, 0, flags);
+ mac_hcksum_set(mp, csum_start - eth_len, csum_stuff - eth_len,
+ len - eth_len, 0, flags);
return (B_TRUE);
}