1

ALSA: pcm: Use automatic cleanup of kfree()

There are common patterns where a temporary buffer is allocated and
freed at the exit, and those can be simplified with the recent cleanup
mechanism via __free(kfree).

A caveat is that some allocations are memdup_user() and they return an
error pointer instead of NULL.  Those need special cares and the value
has to be cleared with no_free_ptr() at the allocation error path.

Other than that, the conversions are straightforward.

No functional changes, only code refactoring.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20240222111509.28390-2-tiwai@suse.de
This commit is contained in:
Takashi Iwai 2024-02-22 12:15:01 +01:00
parent ec89fc1b71
commit ae92139848
3 changed files with 49 additions and 83 deletions

View File

@ -342,7 +342,7 @@ static const char *snd_pcm_oss_format_name(int format)
static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer)
{
struct snd_pcm_info *info;
struct snd_pcm_info *info __free(kfree) = NULL;
int err;
if (! substream)
@ -355,7 +355,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
err = snd_pcm_info(substream, info);
if (err < 0) {
snd_iprintf(buffer, "error %d\n", err);
kfree(info);
return;
}
snd_iprintf(buffer, "card: %d\n", info->card);
@ -369,7 +368,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass);
snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail);
kfree(info);
}
static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,

View File

@ -235,7 +235,7 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
int refine,
struct snd_pcm_hw_params32 __user *data32)
{
struct snd_pcm_hw_params *data;
struct snd_pcm_hw_params *data __free(kfree) = NULL;
struct snd_pcm_runtime *runtime;
int err;
@ -248,34 +248,28 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
return -ENOMEM;
/* only fifo_size (RO from userspace) is different, so just copy all */
if (copy_from_user(data, data32, sizeof(*data32))) {
err = -EFAULT;
goto error;
}
if (copy_from_user(data, data32, sizeof(*data32)))
return -EFAULT;
if (refine) {
err = snd_pcm_hw_refine(substream, data);
if (err < 0)
goto error;
return err;
err = fixup_unreferenced_params(substream, data);
} else {
err = snd_pcm_hw_params(substream, data);
}
if (err < 0)
goto error;
return err;
if (copy_to_user(data32, data, sizeof(*data32)) ||
put_user(data->fifo_size, &data32->fifo_size)) {
err = -EFAULT;
goto error;
}
put_user(data->fifo_size, &data32->fifo_size))
return -EFAULT;
if (! refine) {
unsigned int new_boundary = recalculate_boundary(runtime);
if (new_boundary)
runtime->boundary = new_boundary;
}
error:
kfree(data);
return err;
}
@ -338,7 +332,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
compat_caddr_t buf;
compat_caddr_t __user *bufptr;
u32 frames;
void __user **bufs;
void __user **bufs __free(kfree) = NULL;
int err, ch, i;
if (! substream->runtime)
@ -360,10 +354,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
return -ENOMEM;
for (i = 0; i < ch; i++) {
u32 ptr;
if (get_user(ptr, bufptr)) {
kfree(bufs);
if (get_user(ptr, bufptr))
return -EFAULT;
}
bufs[i] = compat_ptr(ptr);
bufptr++;
}
@ -373,9 +365,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
err = snd_pcm_lib_readv(substream, bufs, frames);
if (err >= 0) {
if (put_user(err, &data32->result))
err = -EFAULT;
return -EFAULT;
}
kfree(bufs);
return err;
}

View File

@ -236,7 +236,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user * _info)
{
struct snd_pcm_info *info;
struct snd_pcm_info *info __free(kfree) = NULL;
int err;
info = kmalloc(sizeof(*info), GFP_KERNEL);
@ -247,7 +247,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
if (copy_to_user(_info, info, sizeof(*info)))
err = -EFAULT;
}
kfree(info);
return err;
}
@ -359,7 +358,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
struct snd_pcm_hw_constraints *constrs =
&substream->runtime->hw_constraints;
unsigned int k;
unsigned int *rstamps;
unsigned int *rstamps __free(kfree) = NULL;
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp;
struct snd_pcm_hw_rule *r;
@ -435,10 +434,8 @@ retry:
}
changed = r->func(params, r);
if (changed < 0) {
err = changed;
goto out;
}
if (changed < 0)
return changed;
/*
* When the parameter is changed, notify it to the caller
@ -469,8 +466,6 @@ retry:
if (again)
goto retry;
out:
kfree(rstamps);
return err;
}
@ -571,26 +566,24 @@ EXPORT_SYMBOL(snd_pcm_hw_refine);
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
struct snd_pcm_hw_params *params;
struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
return PTR_ERR(no_free_ptr(params));
err = snd_pcm_hw_refine(substream, params);
if (err < 0)
goto end;
return err;
err = fixup_unreferenced_params(substream, params);
if (err < 0)
goto end;
return err;
if (copy_to_user(_params, params, sizeof(*params)))
err = -EFAULT;
end:
kfree(params);
return err;
return -EFAULT;
return 0;
}
static int period_to_usecs(struct snd_pcm_runtime *runtime)
@ -864,21 +857,19 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params)
{
struct snd_pcm_hw_params *params;
struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err;
params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params))
return PTR_ERR(params);
return PTR_ERR(no_free_ptr(params));
err = snd_pcm_hw_params(substream, params);
if (err < 0)
goto end;
return err;
if (copy_to_user(_params, params, sizeof(*params)))
err = -EFAULT;
end:
kfree(params);
return -EFAULT;
return err;
}
@ -2271,7 +2262,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
int res = 0;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
struct snd_pcm_group *group, *target_group;
struct snd_pcm_group *group __free(kfree) = NULL;
struct snd_pcm_group *target_group;
bool nonatomic = substream->pcm->nonatomic;
struct fd f = fdget(fd);
@ -2281,6 +2273,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
res = -EBADFD;
goto _badf;
}
pcm_file = f.file->private_data;
substream1 = pcm_file->substream;
@ -2292,8 +2285,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
group = kzalloc(sizeof(*group), GFP_KERNEL);
if (!group) {
res = -ENOMEM;
goto _nolock;
goto _badf;
}
snd_pcm_group_init(group);
down_write(&snd_pcm_link_rwsem);
@ -2324,8 +2318,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
snd_pcm_group_unlock_irq(target_group, nonatomic);
_end:
up_write(&snd_pcm_link_rwsem);
_nolock:
kfree(group);
_badf:
fdput(f);
return res;
@ -3279,7 +3271,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
{
struct snd_xfern xfern;
struct snd_pcm_runtime *runtime = substream->runtime;
void *bufs;
void *bufs __free(kfree) = NULL;
snd_pcm_sframes_t result;
if (runtime->state == SNDRV_PCM_STATE_OPEN)
@ -3293,12 +3285,11 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
if (IS_ERR(bufs))
return PTR_ERR(bufs);
return PTR_ERR(no_free_ptr(bufs));
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
else
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
if (put_user(result, &_xfern->result))
return -EFAULT;
return result < 0 ? result : 0;
@ -3566,7 +3557,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs;
void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(to);
@ -3595,7 +3586,6 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
result = snd_pcm_lib_readv(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
return result;
}
@ -3606,7 +3596,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result;
unsigned long i;
void __user **bufs;
void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(from);
@ -3634,7 +3624,6 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
result = snd_pcm_lib_writev(substream, bufs, frames);
if (result > 0)
result = frames_to_bytes(runtime, result);
kfree(bufs);
return result;
}
@ -4076,8 +4065,8 @@ static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *opara
static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
struct snd_pcm_hw_params *params;
struct snd_pcm_hw_params_old *oparams = NULL;
struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@ -4085,34 +4074,28 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams)) {
err = PTR_ERR(oparams);
goto out;
}
if (IS_ERR(oparams))
return PTR_ERR(no_free_ptr(oparams));
snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_refine(substream, params);
if (err < 0)
goto out_old;
return err;
err = fixup_unreferenced_params(substream, params);
if (err < 0)
goto out_old;
return err;
snd_pcm_hw_convert_to_old_params(oparams, params);
if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
err = -EFAULT;
out_old:
kfree(oparams);
out:
kfree(params);
return err;
return -EFAULT;
return 0;
}
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params_old __user * _oparams)
{
struct snd_pcm_hw_params *params;
struct snd_pcm_hw_params_old *oparams = NULL;
struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err;
params = kmalloc(sizeof(*params), GFP_KERNEL);
@ -4120,24 +4103,18 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams)) {
err = PTR_ERR(oparams);
goto out;
}
if (IS_ERR(oparams))
return PTR_ERR(no_free_ptr(oparams));
snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_params(substream, params);
if (err < 0)
goto out_old;
return err;
snd_pcm_hw_convert_to_old_params(oparams, params);
if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
err = -EFAULT;
out_old:
kfree(oparams);
out:
kfree(params);
return err;
return -EFAULT;
return 0;
}
#endif /* CONFIG_SND_SUPPORT_OLD_API */