Date: Mon, 5 Sep 2016 03:21:31 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r305405 - head/sys/dev/hyperv/vmbus Message-ID: <201609050321.u853LVYa069328@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Mon Sep 5 03:21:31 2016 New Revision: 305405 URL: https://svnweb.freebsd.org/changeset/base/305405 Log: hyperv/vmbus: Stringent header length and total length check. While I'm here, minor style changes. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7752 Modified: head/sys/dev/hyperv/vmbus/vmbus_chan.c head/sys/dev/hyperv/vmbus/vmbus_reg.h Modified: head/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_chan.c Mon Sep 5 02:00:35 2016 (r305404) +++ head/sys/dev/hyperv/vmbus/vmbus_chan.c Mon Sep 5 03:21:31 2016 (r305405) @@ -721,7 +721,20 @@ vmbus_chan_recv(struct vmbus_channel *ch error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) - return error; + return (error); + + if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { + device_printf(chan->ch_dev, "invalid hlen %u\n", + pkt.cph_hlen); + /* XXX this channel is dead actually. */ + return (EIO); + } + if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { + device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n", + pkt.cph_hlen, pkt.cph_tlen); + /* XXX this channel is dead actually. */ + return (EIO); + } hlen = VMBUS_CHANPKT_GETLEN(pkt.cph_hlen); dlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen) - hlen; @@ -729,7 +742,7 @@ vmbus_chan_recv(struct vmbus_channel *ch if (*dlen0 < dlen) { /* Return the size of this packet's data. */ *dlen0 = dlen; - return ENOBUFS; + return (ENOBUFS); } *xactid = pkt.cph_xactid; @@ -739,7 +752,7 @@ vmbus_chan_recv(struct vmbus_channel *ch error = vmbus_rxbr_read(&chan->ch_rxbr, data, dlen, hlen); KASSERT(!error, ("vmbus_rxbr_read failed")); - return 0; + return (0); } int @@ -751,13 +764,26 @@ vmbus_chan_recv_pkt(struct vmbus_channel error = vmbus_rxbr_peek(&chan->ch_rxbr, &pkt, sizeof(pkt)); if (error) - return error; + return (error); + + if (__predict_false(pkt.cph_hlen < VMBUS_CHANPKT_HLEN_MIN)) { + device_printf(chan->ch_dev, "invalid hlen %u\n", + pkt.cph_hlen); + /* XXX this channel is dead actually. */ + return (EIO); + } + if (__predict_false(pkt.cph_hlen > pkt.cph_tlen)) { + device_printf(chan->ch_dev, "invalid hlen %u and tlen %u\n", + pkt.cph_hlen, pkt.cph_tlen); + /* XXX this channel is dead actually. */ + return (EIO); + } pktlen = VMBUS_CHANPKT_GETLEN(pkt.cph_tlen); if (*pktlen0 < pktlen) { /* Return the size of this packet. */ *pktlen0 = pktlen; - return ENOBUFS; + return (ENOBUFS); } *pktlen0 = pktlen; @@ -765,7 +791,7 @@ vmbus_chan_recv_pkt(struct vmbus_channel error = vmbus_rxbr_read(&chan->ch_rxbr, pkt0, pktlen, 0); KASSERT(!error, ("vmbus_rxbr_read failed")); - return 0; + return (0); } static void Modified: head/sys/dev/hyperv/vmbus/vmbus_reg.h ============================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_reg.h Mon Sep 5 02:00:35 2016 (r305404) +++ head/sys/dev/hyperv/vmbus/vmbus_reg.h Mon Sep 5 03:21:31 2016 (r305405) @@ -153,6 +153,9 @@ do { \ #define VMBUS_CHANPKT_TOTLEN(tlen) \ roundup2((tlen), VMBUS_CHANPKT_SIZE_ALIGN) +#define VMBUS_CHANPKT_HLEN_MIN \ + (sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT) + struct vmbus_chanpkt { struct vmbus_chanpkt_hdr cp_hdr; } __packed;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609050321.u853LVYa069328>