virtio-snd control handling trusts the device-provided control type and
value count returned by the device.

That metadata is then used directly to index g_v2a_type_map[] in
virtsnd_kctl_info(), and to size loops and memcpy() operations in
virtsnd_kctl_get() and virtsnd_kctl_put() against fixed-size
virtio_snd_ctl_value and snd_ctl_elem_value arrays.

A buggy or malicious device can therefore trigger out-of-bounds access by
advertising an invalid control type or an oversized value count.

Validate control type and count once in virtsnd_kctl_parse_cfg(), before
querying enumerated items or exposing the control to ALSA.

Fixes: d6568e3de42d ("ALSA: virtio: add support for audio controls")
Cc: [email protected]
Signed-off-by: Cássio Gabriel <[email protected]>
---
 sound/virtio/virtio_kctl.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/sound/virtio/virtio_kctl.c b/sound/virtio/virtio_kctl.c
index ffb903d56297..45f7b6a5b308 100644
--- a/sound/virtio/virtio_kctl.c
+++ b/sound/virtio/virtio_kctl.c
@@ -18,6 +18,21 @@ static const snd_ctl_elem_type_t g_v2a_type_map[] = {
        [VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
 };
 
+/* Map for converting VirtIO types to maximum value counts. */
+static const unsigned int g_v2a_count_map[] = {
+       [VIRTIO_SND_CTL_TYPE_BOOLEAN] =
+               ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
+       [VIRTIO_SND_CTL_TYPE_INTEGER] =
+               ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
+       [VIRTIO_SND_CTL_TYPE_INTEGER64] =
+               ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer64),
+       [VIRTIO_SND_CTL_TYPE_ENUMERATED] =
+               ARRAY_SIZE(((struct virtio_snd_ctl_value 
*)0)->value.enumerated),
+       [VIRTIO_SND_CTL_TYPE_BYTES] =
+               ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.bytes),
+       [VIRTIO_SND_CTL_TYPE_IEC958] = 1
+};
+
 /* Map for converting VirtIO access rights to ALSA access rights. */
 static const unsigned int g_v2a_access_map[] = {
        [VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -36,6 +51,37 @@ static const unsigned int g_v2a_mask_map[] = {
        [VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
 };
 
+static int virtsnd_kctl_validate_info(struct virtio_snd *snd, u32 cid,
+                                     struct virtio_snd_ctl_info *kinfo)
+{
+       struct virtio_device *vdev = snd->vdev;
+       unsigned int type = le32_to_cpu(kinfo->type);
+       unsigned int count = le32_to_cpu(kinfo->count);
+
+       if (type >= ARRAY_SIZE(g_v2a_type_map)) {
+               dev_err(&vdev->dev, "control #%u: unknown type %u\n",
+                       cid, type);
+               return -EINVAL;
+       }
+
+       if (count > g_v2a_count_map[type] ||
+           (type == VIRTIO_SND_CTL_TYPE_IEC958 && count != 1)) {
+               dev_err(&vdev->dev, "control #%u: invalid count %u for type 
%u\n",
+                       cid, count, type);
+               return -EINVAL;
+       }
+
+       if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED &&
+           !le32_to_cpu(kinfo->value.enumerated.items)) {
+               dev_err(&vdev->dev,
+                       "control #%u: no items for enumerated control\n",
+                       cid);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * virtsnd_kctl_info() - Returns information about the control.
  * @kcontrol: ALSA control element.
@@ -385,6 +431,10 @@ int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
                struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
                unsigned int type = le32_to_cpu(kinfo->type);
 
+               rc = virtsnd_kctl_validate_info(snd, i, kinfo);
+               if (rc)
+                       return rc;
+
                if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
                        rc = virtsnd_kctl_get_enum_items(snd, i);
                        if (rc)

---
base-commit: 5bddc5123566e6431fff826fe76a8e378ae9db78
change-id: 20260424-alsa-virtio-validate-kctl-info-2bbe3b5d5d65

Best regards,
--  
Cássio Gabriel <[email protected]>


Reply via email to