Skip to content

Commit 5da9742

Browse files
CassivsGabriellisgregkh
authored andcommitted
ALSA: virtio: Validate control metadata from the device
commit c77a6cb upstream. 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: d6568e3 ("ALSA: virtio: add support for audio controls") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Link: https://patch.msgid.link/20260507-alsa-virtio-validate-kctl-info-v1-1-7404fb12ec37@gmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent df0fe53 commit 5da9742

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

sound/virtio/virtio_kctl.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ static const snd_ctl_elem_type_t g_v2a_type_map[] = {
1818
[VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
1919
};
2020

21+
/* Map for converting VirtIO types to maximum value counts. */
22+
static const unsigned int g_v2a_count_map[] = {
23+
[VIRTIO_SND_CTL_TYPE_BOOLEAN] =
24+
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
25+
[VIRTIO_SND_CTL_TYPE_INTEGER] =
26+
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
27+
[VIRTIO_SND_CTL_TYPE_INTEGER64] =
28+
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer64),
29+
[VIRTIO_SND_CTL_TYPE_ENUMERATED] =
30+
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.enumerated),
31+
[VIRTIO_SND_CTL_TYPE_BYTES] =
32+
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.bytes),
33+
[VIRTIO_SND_CTL_TYPE_IEC958] = 1
34+
};
35+
2136
/* Map for converting VirtIO access rights to ALSA access rights. */
2237
static const unsigned int g_v2a_access_map[] = {
2338
[VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -36,6 +51,37 @@ static const unsigned int g_v2a_mask_map[] = {
3651
[VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
3752
};
3853

54+
static int virtsnd_kctl_validate_info(struct virtio_snd *snd, u32 cid,
55+
struct virtio_snd_ctl_info *kinfo)
56+
{
57+
struct virtio_device *vdev = snd->vdev;
58+
unsigned int type = le32_to_cpu(kinfo->type);
59+
unsigned int count = le32_to_cpu(kinfo->count);
60+
61+
if (type >= ARRAY_SIZE(g_v2a_type_map)) {
62+
dev_err(&vdev->dev, "control #%u: unknown type %u\n",
63+
cid, type);
64+
return -EINVAL;
65+
}
66+
67+
if (count > g_v2a_count_map[type] ||
68+
(type == VIRTIO_SND_CTL_TYPE_IEC958 && count != 1)) {
69+
dev_err(&vdev->dev, "control #%u: invalid count %u for type %u\n",
70+
cid, count, type);
71+
return -EINVAL;
72+
}
73+
74+
if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED &&
75+
!le32_to_cpu(kinfo->value.enumerated.items)) {
76+
dev_err(&vdev->dev,
77+
"control #%u: no items for enumerated control\n",
78+
cid);
79+
return -EINVAL;
80+
}
81+
82+
return 0;
83+
}
84+
3985
/**
4086
* virtsnd_kctl_info() - Returns information about the control.
4187
* @kcontrol: ALSA control element.
@@ -385,6 +431,10 @@ int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
385431
struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
386432
unsigned int type = le32_to_cpu(kinfo->type);
387433

434+
rc = virtsnd_kctl_validate_info(snd, i, kinfo);
435+
if (rc)
436+
return rc;
437+
388438
if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
389439
rc = virtsnd_kctl_get_enum_items(snd, i);
390440
if (rc)

0 commit comments

Comments
 (0)