Skip to content

Commit 860c199

Browse files
takaswietiwai
authored andcommitted
ALSA: control: add dimension validator for userspace elements
The 'dimen' field in struct snd_ctl_elem_info is used to compose all of members in the element as multi-dimensional matrix. The field has four members. Each member represents the width in each dimension level by element member unit. For example, if the members consist of typical two dimensional matrix, the dimen[0] represents the number of rows and dimen[1] represents the number of columns (or vise-versa). The total members in the matrix should be exactly the same as the number of members in the element, while current implementation has no validator of this information. In a view of userspace applications, the information must be valid so that it cannot cause any bugs such as buffer-over-run. This commit adds a validator of dimension information for userspace applications which add new element sets. When they add the element sets with wrong dimension information, they receive -EINVAL. Signed-off-by: Takashi Sakamoto <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent b268c34 commit 860c199

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

sound/core/control.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,36 @@ static int snd_ctl_elem_list(struct snd_card *card,
805805
return 0;
806806
}
807807

808+
static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
809+
{
810+
unsigned int members;
811+
unsigned int i;
812+
813+
if (info->dimen.d[0] == 0)
814+
return true;
815+
816+
members = 1;
817+
for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
818+
if (info->dimen.d[i] == 0)
819+
break;
820+
members *= info->dimen.d[i];
821+
822+
/*
823+
* info->count should be validated in advance, to guarantee
824+
* calculation soundness.
825+
*/
826+
if (members > info->count)
827+
return false;
828+
}
829+
830+
for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
831+
if (info->dimen.d[i] > 0)
832+
return false;
833+
}
834+
835+
return members == info->count;
836+
}
837+
808838
static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
809839
struct snd_ctl_elem_info *info)
810840
{
@@ -1272,6 +1302,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
12721302
if (info->count < 1 ||
12731303
info->count > max_value_counts[info->type])
12741304
return -EINVAL;
1305+
if (!validate_element_member_dimension(info))
1306+
return -EINVAL;
12751307
private_size = value_sizes[info->type] * info->count;
12761308

12771309
/*

0 commit comments

Comments
 (0)