mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
ALSA: control: Use scoped cleanup for user control buffers
User-defined control TLV data and enum names are copied from user space with vmemdup_user() before being installed in the user_element. Until ownership is transferred, these temporary buffers have to be released on every validation exit. Use __free(kvfree) for the temporary buffers and no_free_ptr() when ownership is transferred to the user_element. This removes the manual kvfree() calls from the unchanged-TLV and enum-name validation paths, makes the ownership hand-off explicit, and keeps the existing allocation accounting and ABI unchanged. No functional change is intended. Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20260604-alsa-scoped-cleanups-v1-1-10c43152a728@gmail.com
This commit is contained in:
parent
3580bc5352
commit
83615ff7c6
|
|
@ -1550,7 +1550,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
|||
unsigned int size)
|
||||
{
|
||||
struct user_element *ue = snd_kcontrol_chip(kctl);
|
||||
unsigned int *container;
|
||||
unsigned int mask = 0;
|
||||
int i;
|
||||
int change;
|
||||
|
|
@ -1564,17 +1563,16 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
|||
if (check_user_elem_overflow(ue->card, (ssize_t)(size - ue->tlv_data_size)))
|
||||
return -ENOMEM;
|
||||
|
||||
container = vmemdup_user(buf, size);
|
||||
unsigned int *container __free(kvfree) = vmemdup_user(buf, size);
|
||||
|
||||
if (IS_ERR(container))
|
||||
return PTR_ERR(container);
|
||||
|
||||
change = ue->tlv_data_size != size;
|
||||
if (!change)
|
||||
change = memcmp(ue->tlv_data, container, size) != 0;
|
||||
if (!change) {
|
||||
kvfree(container);
|
||||
if (!change)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ue->tlv_data == NULL) {
|
||||
/* Now TLV data is available. */
|
||||
|
|
@ -1587,7 +1585,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
|
|||
kvfree(ue->tlv_data);
|
||||
}
|
||||
|
||||
ue->tlv_data = container;
|
||||
ue->tlv_data = no_free_ptr(container);
|
||||
ue->tlv_data_size = size;
|
||||
// decremented at private_free.
|
||||
ue->card->user_ctl_alloc_size += size;
|
||||
|
|
@ -1628,7 +1626,6 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
|
|||
/* called in controls_rwsem write lock */
|
||||
static int snd_ctl_elem_init_enum_names(struct user_element *ue)
|
||||
{
|
||||
char *names, *p;
|
||||
size_t buf_len, name_len;
|
||||
unsigned int i;
|
||||
const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
|
||||
|
|
@ -1641,27 +1638,28 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
|
|||
|
||||
if (check_user_elem_overflow(ue->card, buf_len))
|
||||
return -ENOMEM;
|
||||
names = vmemdup_user((const void __user *)user_ptrval, buf_len);
|
||||
char *names __free(kvfree) = vmemdup_user((const void __user *)user_ptrval,
|
||||
buf_len);
|
||||
|
||||
if (IS_ERR(names))
|
||||
return PTR_ERR(names);
|
||||
|
||||
/* check that there are enough valid names */
|
||||
p = names;
|
||||
char *p = names;
|
||||
|
||||
for (i = 0; i < ue->info.value.enumerated.items; ++i) {
|
||||
if (buf_len == 0) {
|
||||
kvfree(names);
|
||||
if (buf_len == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
name_len = strnlen(p, buf_len);
|
||||
if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
|
||||
kvfree(names);
|
||||
if (name_len == 0 || name_len >= 64 || name_len == buf_len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p += name_len + 1;
|
||||
buf_len -= name_len + 1;
|
||||
}
|
||||
|
||||
ue->priv_data = names;
|
||||
ue->priv_data = no_free_ptr(names);
|
||||
ue->info.value.enumerated.names_ptr = 0;
|
||||
// increment the allocation size; decremented again at private_free.
|
||||
ue->card->user_ctl_alloc_size += ue->info.value.enumerated.names_length;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user