]> git.baikalelectronics.ru Git - kernel.git/commitdiff
vdpa/mlx5: add validation for VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET command
authorSi-Wei Liu <si-wei.liu@oracle.com>
Sat, 15 Jan 2022 00:28:01 +0000 (19:28 -0500)
committerMichael S. Tsirkin <mst@redhat.com>
Fri, 4 Mar 2022 16:56:34 +0000 (11:56 -0500)
When control vq receives a VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET command
request from the driver, presently there is no validation against the
number of queue pairs to configure, or even if multiqueue had been
negotiated or not is unverified. This may lead to kernel panic due to
uninitialized resource for the queues were there any bogus request
sent down by untrusted driver. Tie up the loose ends there.

Fixes: 52893733f2c5 ("vdpa/mlx5: Add multiqueue support")
Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com>
Link: https://lore.kernel.org/r/1642206481-30721-4-git-send-email-si-wei.liu@oracle.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eli Cohen <elic@nvidia.com>
Acked-by: Jason Wang <jasowang@redhat.com>
drivers/vdpa/mlx5/net/mlx5_vnet.c

index 1ffbd20fcf21bbaa59ce711778392abc1363dc73..d0f91078600e9a5fa09b79d408c6f4359436dc31 100644 (file)
@@ -1563,11 +1563,27 @@ static virtio_net_ctrl_ack handle_ctrl_mq(struct mlx5_vdpa_dev *mvdev, u8 cmd)
 
        switch (cmd) {
        case VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET:
+               /* This mq feature check aligns with pre-existing userspace
+                * implementation.
+                *
+                * Without it, an untrusted driver could fake a multiqueue config
+                * request down to a non-mq device that may cause kernel to
+                * panic due to uninitialized resources for extra vqs. Even with
+                * a well behaving guest driver, it is not expected to allow
+                * changing the number of vqs on a non-mq device.
+                */
+               if (!MLX5_FEATURE(mvdev, VIRTIO_NET_F_MQ))
+                       break;
+
                read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->riov, (void *)&mq, sizeof(mq));
                if (read != sizeof(mq))
                        break;
 
                newqps = mlx5vdpa16_to_cpu(mvdev, mq.virtqueue_pairs);
+               if (newqps < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
+                   newqps > mlx5_vdpa_max_qps(mvdev->max_vqs))
+                       break;
+
                if (ndev->cur_num_vqs == 2 * newqps) {
                        status = VIRTIO_NET_OK;
                        break;