NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/51451: if_vioif.c aliases Tx and Rx virtio_net_hdrs



>Number:         51451
>Category:       kern
>Synopsis:       if_vioif.c aliases Tx and Rx virtio_net_hdrs
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 29 17:45:00 +0000 2016
>Originator:     Venkatesh Srinivas
>Release:        7.0.1; 7.99.36
>Organization:
Google, Inc
>Environment:
NetBSD 7.99.36 (GENERIC)
amd64
>Description:
The virtio-net driver, if_vioif.c, preallocates virtio_net_hdr structs for both Tx and Rx paths. It also preconstructs bus_dmamaps for the preallocated structures.

Unfortunately the driver has a typo and uses the Rx allocation for both Rx and Tx dmamaps; this results in reuse of possibly-live Rx virtio_net_hdrs for Tx. virtio-net devices may see Tx headers with Rx fields set, which they may drop.

>How-To-Repeat:
Boot NetBSD 7.x+ or -CURRENT on a virtual machine with a virtio-net interface. Attempt to send and receive network traffic concurrently. Examine device-side address ranges.
>Fix:
Tested with Google Compute Engine's hypervisor and with QEMU 2.0.0 without
vhost.

--- if_vioif.c.orig     2016-08-24 16:16:28.138160100 +0000
+++ if_vioif.c  2016-08-24 16:16:56.416410543 +0000
@@ -420,21 +420,21 @@ vioif_alloc_mems(struct vioif_softc *sc)
                }                                                     \
        } while (0)
        for (i = 0; i < rxqsize; i++) {
                C_L1(rxhdr_dmamaps[i], rx_hdrs[i],
                    sizeof(struct virtio_net_hdr), 1,
                    READ, "rx header");
                C(rx_dmamaps[i], NULL, MCLBYTES, 1, 0, "rx payload");
        }

        for (i = 0; i < txqsize; i++) {
-               C_L1(txhdr_dmamaps[i], rx_hdrs[i],
+               C_L1(txhdr_dmamaps[i], tx_hdrs[i],
                    sizeof(struct virtio_net_hdr), 1,
                    WRITE, "tx header");
                C(tx_dmamaps[i], NULL, ETHER_MAX_LEN, 16 /* XXX */, 0,
                  "tx payload");
        }

        if (vsc->sc_nvqs == 3) {
                /* control vq class & command */
                C_L2(ctrl_cmd_dmamap, ctrl_cmd,
                    sizeof(struct virtio_net_ctrl_cmd), 1, WRITE,



Home | Main Index | Thread Index | Old Index