mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
ctl: add dimension validator
Linux 4.7 or former have no validator of dimension information. This can causes an issue related to user-defined element set. For example, When calculated total members in multi-dimensional matrix is larger than actual capacity of snd_ctl_elem_value_t, processes to handle the element can cause buffer-over-run. For backward portability of this userspace library, this commit adds a validator of dimension information. When userspace applications give invalid dimension information to APIs to add element set, they receive -EINVAL. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
3ef712844f
commit
025e451b83
1 changed files with 42 additions and 0 deletions
|
|
@ -91,6 +91,7 @@ I/O operations.
|
|||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/poll.h>
|
||||
#include <stdbool.h>
|
||||
#include "control_local.h"
|
||||
|
||||
/**
|
||||
|
|
@ -302,6 +303,32 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info)
|
|||
return ctl->ops->element_info(ctl, info);
|
||||
}
|
||||
|
||||
static bool validate_element_member_dimension(snd_ctl_elem_info_t *info)
|
||||
{
|
||||
unsigned int members;
|
||||
unsigned int i;
|
||||
|
||||
if (info->dimen.d[0] == 0)
|
||||
return true;
|
||||
|
||||
members = 1;
|
||||
for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
|
||||
if (info->dimen.d[i] == 0)
|
||||
break;
|
||||
members *= info->dimen.d[i];
|
||||
|
||||
if (members > info->count)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
|
||||
if (info->dimen.d[i] > 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return members == info->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create and add some user-defined control elements of integer type.
|
||||
* \param ctl A handle of backend module for control interface.
|
||||
|
|
@ -366,6 +393,9 @@ int snd_ctl_elem_add_integer_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
|
|||
info->value.integer.max = max;
|
||||
info->value.integer.step = step;
|
||||
|
||||
if (!validate_element_member_dimension(info))
|
||||
return -EINVAL;
|
||||
|
||||
err = ctl->ops->element_add(ctl, info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
@ -451,6 +481,9 @@ int snd_ctl_elem_add_integer64_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
|
|||
info->value.integer64.max = max;
|
||||
info->value.integer64.step = step;
|
||||
|
||||
if (!validate_element_member_dimension(info))
|
||||
return -EINVAL;
|
||||
|
||||
err = ctl->ops->element_add(ctl, info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
@ -524,6 +557,9 @@ int snd_ctl_elem_add_boolean_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
|
|||
info->value.integer.min = 0;
|
||||
info->value.integer.max = 1;
|
||||
|
||||
if (!validate_element_member_dimension(info))
|
||||
return -EINVAL;
|
||||
|
||||
return ctl->ops->element_add(ctl, info);
|
||||
}
|
||||
|
||||
|
|
@ -605,6 +641,9 @@ int snd_ctl_elem_add_enumerated_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
|
|||
p += strlen(labels[i]) + 1;
|
||||
}
|
||||
|
||||
if (!validate_element_member_dimension(info))
|
||||
return -EINVAL;
|
||||
|
||||
err = ctl->ops->element_add(ctl, info);
|
||||
|
||||
free(buf);
|
||||
|
|
@ -663,6 +702,9 @@ int snd_ctl_elem_add_bytes_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
|
|||
info->owner = element_count;
|
||||
info->count = member_count;
|
||||
|
||||
if (!validate_element_member_dimension(info))
|
||||
return -EINVAL;
|
||||
|
||||
return ctl->ops->element_add(ctl, info);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue