Module Name:    src
Committed By:   martin
Date:           Fri Dec 22 13:48:59 UTC 2023

Modified Files:
        src/sys/arch/xen/xen [netbsd-10]: xennetback_xenbus.c

Log Message:
Pull up following revision(s) (requested by bouyer in ticket #514):

        sys/arch/xen/xen/xennetback_xenbus.c: revision 1.124 (patch)

sanity check the fragments we get from the guest and reject the whole packet
if it fails. Make sure we don't KASSERT() on data we get from the frontend.


To generate a diff of this commit:
cvs rdiff -u -r1.108.4.2 -r1.108.4.3 src/sys/arch/xen/xen/xennetback_xenbus.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/xennetback_xenbus.c
diff -u src/sys/arch/xen/xen/xennetback_xenbus.c:1.108.4.2 src/sys/arch/xen/xen/xennetback_xenbus.c:1.108.4.3
--- src/sys/arch/xen/xen/xennetback_xenbus.c:1.108.4.2	Fri Aug  4 19:53:43 2023
+++ src/sys/arch/xen/xen/xennetback_xenbus.c	Fri Dec 22 13:48:59 2023
@@ -1,4 +1,4 @@
-/*      $NetBSD: xennetback_xenbus.c,v 1.108.4.2 2023/08/04 19:53:43 martin Exp $      */
+/*      $NetBSD: xennetback_xenbus.c,v 1.108.4.3 2023/12/22 13:48:59 martin Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.108.4.2 2023/08/04 19:53:43 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.108.4.3 2023/12/22 13:48:59 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -615,7 +615,7 @@ xennetback_tx_response(struct xnetback_i
 }
 
 static const char *
-xennetback_tx_check_packet(const netif_tx_request_t *txreq)
+xennetback_tx_check_packet(const netif_tx_request_t *txreq, bool first)
 {
 	if (__predict_false((txreq->flags & NETTXF_more_data) == 0 &&
 	    txreq->offset + txreq->size > PAGE_SIZE))
@@ -624,6 +624,10 @@ xennetback_tx_check_packet(const netif_t
 	if (__predict_false(txreq->size > ETHER_MAX_LEN_JUMBO))
 		return "bigger then jumbo";
 
+	if (first &&
+	    __predict_false(txreq->size < ETHER_HDR_LEN))
+		return "too short";
+
 	return NULL;
 }
 
@@ -788,7 +792,11 @@ xennetback_tx_m0len_fragment(struct xnet
 	*cntp = 1;
 	do {
 		txreq = RING_GET_REQUEST(&xneti->xni_txring, req_cons);
-		KASSERT(m0_len > txreq->size);
+		if (m0_len <= txreq->size || *cntp > XEN_NETIF_NR_SLOTS_MIN)
+			return -1;
+		if (RING_REQUEST_CONS_OVERFLOW(&xneti->xni_txring, req_cons))
+			return -1;
+			
 		m0_len -= txreq->size;
 		req_cons++;
 		(*cntp)++;
@@ -808,8 +816,9 @@ xennetback_evthandler(void *arg)
 	RING_IDX req_cons;
 	int queued = 0, m0_len = 0;
 	struct xnetback_xstate *xst;
-	const bool discard = ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
+	const bool nupnrun = ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
 	    (IFF_UP | IFF_RUNNING));
+	bool discard = 0;
 
 	XENPRINTF(("xennetback_evthandler "));
 	req_cons = xneti->xni_txring.req_cons;
@@ -827,9 +836,10 @@ xennetback_evthandler(void *arg)
 		XENPRINTF(("%s pkt size %d\n", xneti->xni_if.if_xname,
 		    txreq.size));
 		req_cons++;
-		if (__predict_false(discard)) {
+		if (__predict_false(nupnrun || discard)) {
 			/* interface not up, drop all requests */
 			if_statinc(ifp, if_iqdrops);
+			discard = (txreq.flags & NETTXF_more_data) != 0;
 			xennetback_tx_response(xneti, txreq.id,
 			    NETIF_RSP_DROPPED);
 			continue;
@@ -838,10 +848,12 @@ xennetback_evthandler(void *arg)
 		/*
 		 * Do some sanity checks, and queue copy of the data.
 		 */
-		const char *msg = xennetback_tx_check_packet(&txreq);
+		const char *msg = xennetback_tx_check_packet(&txreq,
+		    m0 == NULL);
 		if (__predict_false(msg != NULL)) {
 			printf("%s: packet with size %d is %s\n",
 			    ifp->if_xname, txreq.size, msg);
+			discard = (txreq.flags & NETTXF_more_data) != 0;
 			xennetback_tx_response(xneti, txreq.id,
 			    NETIF_RSP_ERROR);
 			if_statinc(ifp, if_ierrors);
@@ -859,6 +871,7 @@ mbuf_fail:
 			xennetback_tx_copy_abort(ifp, xneti, queued);
 			queued = 0;
 			m0 = NULL;
+			discard = (txreq.flags & NETTXF_more_data) != 0;
 			xennetback_tx_response(xneti, txreq.id,
 			    NETIF_RSP_DROPPED);
 			if_statinc(ifp, if_ierrors);
@@ -876,6 +889,14 @@ mbuf_fail:
 			int cnt;
 			m0_len = xennetback_tx_m0len_fragment(xneti,
 			    txreq.size, req_cons, &cnt);
+			if (m0_len < 0) {
+				m_freem(m);
+				discard = 1;
+				xennetback_tx_response(xneti, txreq.id,
+				    NETIF_RSP_DROPPED);
+				if_statinc(ifp, if_ierrors);
+				continue;
+			}
 			m->m_len = m0_len;
 			KASSERT(cnt <= XEN_NETIF_NR_SLOTS_MIN);
 
@@ -884,7 +905,6 @@ mbuf_fail:
 				 * Flush queue if too full to fit this
 				 * new packet whole.
 				 */
-				KASSERT(m0 == NULL);
 				xennetback_tx_copy_process(ifp, xneti, queued);
 				queued = 0;
 			}

Reply via email to