Commit ae921398 authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20240222111509.28390-2-tiwai@suse.de
parent ec89fc1b
...@@ -342,7 +342,7 @@ static const char *snd_pcm_oss_format_name(int format) ...@@ -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, static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
struct snd_info_buffer *buffer) struct snd_info_buffer *buffer)
{ {
struct snd_pcm_info *info; struct snd_pcm_info *info __free(kfree) = NULL;
int err; int err;
if (! substream) if (! substream)
...@@ -355,7 +355,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, ...@@ -355,7 +355,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream,
err = snd_pcm_info(substream, info); err = snd_pcm_info(substream, info);
if (err < 0) { if (err < 0) {
snd_iprintf(buffer, "error %d\n", err); snd_iprintf(buffer, "error %d\n", err);
kfree(info);
return; return;
} }
snd_iprintf(buffer, "card: %d\n", info->card); snd_iprintf(buffer, "card: %d\n", info->card);
...@@ -369,7 +368,6 @@ static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, ...@@ -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, "subclass: %d\n", info->dev_subclass);
snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count); snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count);
snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail); 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, static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
......
...@@ -235,7 +235,7 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, ...@@ -235,7 +235,7 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
int refine, int refine,
struct snd_pcm_hw_params32 __user *data32) 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; struct snd_pcm_runtime *runtime;
int err; int err;
...@@ -248,34 +248,28 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream, ...@@ -248,34 +248,28 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
return -ENOMEM; return -ENOMEM;
/* only fifo_size (RO from userspace) is different, so just copy all */ /* only fifo_size (RO from userspace) is different, so just copy all */
if (copy_from_user(data, data32, sizeof(*data32))) { if (copy_from_user(data, data32, sizeof(*data32)))
err = -EFAULT; return -EFAULT;
goto error;
}
if (refine) { if (refine) {
err = snd_pcm_hw_refine(substream, data); err = snd_pcm_hw_refine(substream, data);
if (err < 0) if (err < 0)
goto error; return err;
err = fixup_unreferenced_params(substream, data); err = fixup_unreferenced_params(substream, data);
} else { } else {
err = snd_pcm_hw_params(substream, data); err = snd_pcm_hw_params(substream, data);
} }
if (err < 0) if (err < 0)
goto error; return err;
if (copy_to_user(data32, data, sizeof(*data32)) || if (copy_to_user(data32, data, sizeof(*data32)) ||
put_user(data->fifo_size, &data32->fifo_size)) { put_user(data->fifo_size, &data32->fifo_size))
err = -EFAULT; return -EFAULT;
goto error;
}
if (! refine) { if (! refine) {
unsigned int new_boundary = recalculate_boundary(runtime); unsigned int new_boundary = recalculate_boundary(runtime);
if (new_boundary) if (new_boundary)
runtime->boundary = new_boundary; runtime->boundary = new_boundary;
} }
error:
kfree(data);
return err; return err;
} }
...@@ -338,7 +332,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, ...@@ -338,7 +332,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
compat_caddr_t buf; compat_caddr_t buf;
compat_caddr_t __user *bufptr; compat_caddr_t __user *bufptr;
u32 frames; u32 frames;
void __user **bufs; void __user **bufs __free(kfree) = NULL;
int err, ch, i; int err, ch, i;
if (! substream->runtime) if (! substream->runtime)
...@@ -360,10 +354,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, ...@@ -360,10 +354,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
return -ENOMEM; return -ENOMEM;
for (i = 0; i < ch; i++) { for (i = 0; i < ch; i++) {
u32 ptr; u32 ptr;
if (get_user(ptr, bufptr)) { if (get_user(ptr, bufptr))
kfree(bufs);
return -EFAULT; return -EFAULT;
}
bufs[i] = compat_ptr(ptr); bufs[i] = compat_ptr(ptr);
bufptr++; bufptr++;
} }
...@@ -373,9 +365,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, ...@@ -373,9 +365,8 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
err = snd_pcm_lib_readv(substream, bufs, frames); err = snd_pcm_lib_readv(substream, bufs, frames);
if (err >= 0) { if (err >= 0) {
if (put_user(err, &data32->result)) if (put_user(err, &data32->result))
err = -EFAULT; return -EFAULT;
} }
kfree(bufs);
return err; return err;
} }
......
...@@ -236,7 +236,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) ...@@ -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, int snd_pcm_info_user(struct snd_pcm_substream *substream,
struct snd_pcm_info __user * _info) struct snd_pcm_info __user * _info)
{ {
struct snd_pcm_info *info; struct snd_pcm_info *info __free(kfree) = NULL;
int err; int err;
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
...@@ -247,7 +247,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream, ...@@ -247,7 +247,6 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
if (copy_to_user(_info, info, sizeof(*info))) if (copy_to_user(_info, info, sizeof(*info)))
err = -EFAULT; err = -EFAULT;
} }
kfree(info);
return err; return err;
} }
...@@ -359,7 +358,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -359,7 +358,7 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
struct snd_pcm_hw_constraints *constrs = struct snd_pcm_hw_constraints *constrs =
&substream->runtime->hw_constraints; &substream->runtime->hw_constraints;
unsigned int k; unsigned int k;
unsigned int *rstamps; unsigned int *rstamps __free(kfree) = NULL;
unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp; unsigned int stamp;
struct snd_pcm_hw_rule *r; struct snd_pcm_hw_rule *r;
...@@ -435,10 +434,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -435,10 +434,8 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
} }
changed = r->func(params, r); changed = r->func(params, r);
if (changed < 0) { if (changed < 0)
err = changed; return changed;
goto out;
}
/* /*
* When the parameter is changed, notify it to the caller * When the parameter is changed, notify it to the caller
...@@ -469,8 +466,6 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream, ...@@ -469,8 +466,6 @@ static int constrain_params_by_rules(struct snd_pcm_substream *substream,
if (again) if (again)
goto retry; goto retry;
out:
kfree(rstamps);
return err; return err;
} }
...@@ -571,26 +566,24 @@ EXPORT_SYMBOL(snd_pcm_hw_refine); ...@@ -571,26 +566,24 @@ EXPORT_SYMBOL(snd_pcm_hw_refine);
static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params) struct snd_pcm_hw_params __user * _params)
{ {
struct snd_pcm_hw_params *params; struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err; int err;
params = memdup_user(_params, sizeof(*params)); params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params)) if (IS_ERR(params))
return PTR_ERR(params); return PTR_ERR(no_free_ptr(params));
err = snd_pcm_hw_refine(substream, params); err = snd_pcm_hw_refine(substream, params);
if (err < 0) if (err < 0)
goto end; return err;
err = fixup_unreferenced_params(substream, params); err = fixup_unreferenced_params(substream, params);
if (err < 0) if (err < 0)
goto end; return err;
if (copy_to_user(_params, params, sizeof(*params))) if (copy_to_user(_params, params, sizeof(*params)))
err = -EFAULT; return -EFAULT;
end: return 0;
kfree(params);
return err;
} }
static int period_to_usecs(struct snd_pcm_runtime *runtime) 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, ...@@ -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, static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params __user * _params) struct snd_pcm_hw_params __user * _params)
{ {
struct snd_pcm_hw_params *params; struct snd_pcm_hw_params *params __free(kfree) = NULL;
int err; int err;
params = memdup_user(_params, sizeof(*params)); params = memdup_user(_params, sizeof(*params));
if (IS_ERR(params)) if (IS_ERR(params))
return PTR_ERR(params); return PTR_ERR(no_free_ptr(params));
err = snd_pcm_hw_params(substream, params); err = snd_pcm_hw_params(substream, params);
if (err < 0) if (err < 0)
goto end; return err;
if (copy_to_user(_params, params, sizeof(*params))) if (copy_to_user(_params, params, sizeof(*params)))
err = -EFAULT; return -EFAULT;
end:
kfree(params);
return err; return err;
} }
...@@ -2271,7 +2262,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -2271,7 +2262,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
int res = 0; int res = 0;
struct snd_pcm_file *pcm_file; struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1; 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; bool nonatomic = substream->pcm->nonatomic;
struct fd f = fdget(fd); struct fd f = fdget(fd);
...@@ -2281,6 +2273,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -2281,6 +2273,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
res = -EBADFD; res = -EBADFD;
goto _badf; goto _badf;
} }
pcm_file = f.file->private_data; pcm_file = f.file->private_data;
substream1 = pcm_file->substream; substream1 = pcm_file->substream;
...@@ -2292,8 +2285,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -2292,8 +2285,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
group = kzalloc(sizeof(*group), GFP_KERNEL); group = kzalloc(sizeof(*group), GFP_KERNEL);
if (!group) { if (!group) {
res = -ENOMEM; res = -ENOMEM;
goto _nolock; goto _badf;
} }
snd_pcm_group_init(group); snd_pcm_group_init(group);
down_write(&snd_pcm_link_rwsem); down_write(&snd_pcm_link_rwsem);
...@@ -2324,8 +2318,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) ...@@ -2324,8 +2318,6 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
snd_pcm_group_unlock_irq(target_group, nonatomic); snd_pcm_group_unlock_irq(target_group, nonatomic);
_end: _end:
up_write(&snd_pcm_link_rwsem); up_write(&snd_pcm_link_rwsem);
_nolock:
kfree(group);
_badf: _badf:
fdput(f); fdput(f);
return res; return res;
...@@ -3279,7 +3271,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, ...@@ -3279,7 +3271,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
{ {
struct snd_xfern xfern; struct snd_xfern xfern;
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
void *bufs; void *bufs __free(kfree) = NULL;
snd_pcm_sframes_t result; snd_pcm_sframes_t result;
if (runtime->state == SNDRV_PCM_STATE_OPEN) if (runtime->state == SNDRV_PCM_STATE_OPEN)
...@@ -3293,12 +3285,11 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, ...@@ -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); bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels);
if (IS_ERR(bufs)) if (IS_ERR(bufs))
return PTR_ERR(bufs); return PTR_ERR(no_free_ptr(bufs));
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_lib_writev(substream, bufs, xfern.frames); result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
else else
result = snd_pcm_lib_readv(substream, bufs, xfern.frames); result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
kfree(bufs);
if (put_user(result, &_xfern->result)) if (put_user(result, &_xfern->result))
return -EFAULT; return -EFAULT;
return result < 0 ? result : 0; return result < 0 ? result : 0;
...@@ -3566,7 +3557,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) ...@@ -3566,7 +3557,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result; snd_pcm_sframes_t result;
unsigned long i; unsigned long i;
void __user **bufs; void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(to); const struct iovec *iov = iter_iov(to);
...@@ -3595,7 +3586,6 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *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); result = snd_pcm_lib_readv(substream, bufs, frames);
if (result > 0) if (result > 0)
result = frames_to_bytes(runtime, result); result = frames_to_bytes(runtime, result);
kfree(bufs);
return result; return result;
} }
...@@ -3606,7 +3596,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) ...@@ -3606,7 +3596,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
snd_pcm_sframes_t result; snd_pcm_sframes_t result;
unsigned long i; unsigned long i;
void __user **bufs; void __user **bufs __free(kfree) = NULL;
snd_pcm_uframes_t frames; snd_pcm_uframes_t frames;
const struct iovec *iov = iter_iov(from); const struct iovec *iov = iter_iov(from);
...@@ -3634,7 +3624,6 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *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); result = snd_pcm_lib_writev(substream, bufs, frames);
if (result > 0) if (result > 0)
result = frames_to_bytes(runtime, result); result = frames_to_bytes(runtime, result);
kfree(bufs);
return result; return result;
} }
...@@ -4076,8 +4065,8 @@ static void snd_pcm_hw_convert_to_old_params(struct snd_pcm_hw_params_old *opara ...@@ -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, 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_old __user * _oparams)
{ {
struct snd_pcm_hw_params *params; struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams = NULL; struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err; int err;
params = kmalloc(sizeof(*params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL);
...@@ -4085,34 +4074,28 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, ...@@ -4085,34 +4074,28 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
return -ENOMEM; return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams)); oparams = memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams)) { if (IS_ERR(oparams))
err = PTR_ERR(oparams); return PTR_ERR(no_free_ptr(oparams));
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams); snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_refine(substream, params); err = snd_pcm_hw_refine(substream, params);
if (err < 0) if (err < 0)
goto out_old; return err;
err = fixup_unreferenced_params(substream, params); err = fixup_unreferenced_params(substream, params);
if (err < 0) if (err < 0)
goto out_old; return err;
snd_pcm_hw_convert_to_old_params(oparams, params); snd_pcm_hw_convert_to_old_params(oparams, params);
if (copy_to_user(_oparams, oparams, sizeof(*oparams))) if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
err = -EFAULT; return -EFAULT;
out_old: return 0;
kfree(oparams);
out:
kfree(params);
return err;
} }
static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, 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_old __user * _oparams)
{ {
struct snd_pcm_hw_params *params; struct snd_pcm_hw_params *params __free(kfree) = NULL;
struct snd_pcm_hw_params_old *oparams = NULL; struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL;
int err; int err;
params = kmalloc(sizeof(*params), GFP_KERNEL); params = kmalloc(sizeof(*params), GFP_KERNEL);
...@@ -4120,24 +4103,18 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, ...@@ -4120,24 +4103,18 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
return -ENOMEM; return -ENOMEM;
oparams = memdup_user(_oparams, sizeof(*oparams)); oparams = memdup_user(_oparams, sizeof(*oparams));
if (IS_ERR(oparams)) { if (IS_ERR(oparams))
err = PTR_ERR(oparams); return PTR_ERR(no_free_ptr(oparams));
goto out;
}
snd_pcm_hw_convert_from_old_params(params, oparams); snd_pcm_hw_convert_from_old_params(params, oparams);
err = snd_pcm_hw_params(substream, params); err = snd_pcm_hw_params(substream, params);
if (err < 0) if (err < 0)
goto out_old; return err;
snd_pcm_hw_convert_to_old_params(oparams, params); snd_pcm_hw_convert_to_old_params(oparams, params);
if (copy_to_user(_oparams, oparams, sizeof(*oparams))) if (copy_to_user(_oparams, oparams, sizeof(*oparams)))
err = -EFAULT; return -EFAULT;
out_old: return 0;
kfree(oparams);
out:
kfree(params);
return err;
} }
#endif /* CONFIG_SND_SUPPORT_OLD_API */ #endif /* CONFIG_SND_SUPPORT_OLD_API */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment