Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+49 -83
+1 -3
sound/core/pcm.c
··· 342 342 static void snd_pcm_proc_info_read(struct snd_pcm_substream *substream, 343 343 struct snd_info_buffer *buffer) 344 344 { 345 - struct snd_pcm_info *info; 345 + struct snd_pcm_info *info __free(kfree) = NULL; 346 346 int err; 347 347 348 348 if (! substream) ··· 355 355 err = snd_pcm_info(substream, info); 356 356 if (err < 0) { 357 357 snd_iprintf(buffer, "error %d\n", err); 358 - kfree(info); 359 358 return; 360 359 } 361 360 snd_iprintf(buffer, "card: %d\n", info->card); ··· 368 369 snd_iprintf(buffer, "subclass: %d\n", info->dev_subclass); 369 370 snd_iprintf(buffer, "subdevices_count: %d\n", info->subdevices_count); 370 371 snd_iprintf(buffer, "subdevices_avail: %d\n", info->subdevices_avail); 371 - kfree(info); 372 372 } 373 373 374 374 static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
+10 -19
sound/core/pcm_compat.c
··· 235 235 int refine, 236 236 struct snd_pcm_hw_params32 __user *data32) 237 237 { 238 - struct snd_pcm_hw_params *data; 238 + struct snd_pcm_hw_params *data __free(kfree) = NULL; 239 239 struct snd_pcm_runtime *runtime; 240 240 int err; 241 241 ··· 248 248 return -ENOMEM; 249 249 250 250 /* only fifo_size (RO from userspace) is different, so just copy all */ 251 - if (copy_from_user(data, data32, sizeof(*data32))) { 252 - err = -EFAULT; 253 - goto error; 254 - } 251 + if (copy_from_user(data, data32, sizeof(*data32))) 252 + return -EFAULT; 255 253 256 254 if (refine) { 257 255 err = snd_pcm_hw_refine(substream, data); 258 256 if (err < 0) 259 - goto error; 257 + return err; 260 258 err = fixup_unreferenced_params(substream, data); 261 259 } else { 262 260 err = snd_pcm_hw_params(substream, data); 263 261 } 264 262 if (err < 0) 265 - goto error; 263 + return err; 266 264 if (copy_to_user(data32, data, sizeof(*data32)) || 267 - put_user(data->fifo_size, &data32->fifo_size)) { 268 - err = -EFAULT; 269 - goto error; 270 - } 265 + put_user(data->fifo_size, &data32->fifo_size)) 266 + return -EFAULT; 271 267 272 268 if (! refine) { 273 269 unsigned int new_boundary = recalculate_boundary(runtime); 274 270 if (new_boundary) 275 271 runtime->boundary = new_boundary; 276 272 } 277 - error: 278 - kfree(data); 279 273 return err; 280 274 } 281 275 ··· 332 338 compat_caddr_t buf; 333 339 compat_caddr_t __user *bufptr; 334 340 u32 frames; 335 - void __user **bufs; 341 + void __user **bufs __free(kfree) = NULL; 336 342 int err, ch, i; 337 343 338 344 if (! substream->runtime) ··· 354 360 return -ENOMEM; 355 361 for (i = 0; i < ch; i++) { 356 362 u32 ptr; 357 - if (get_user(ptr, bufptr)) { 358 - kfree(bufs); 363 + if (get_user(ptr, bufptr)) 359 364 return -EFAULT; 360 - } 361 365 bufs[i] = compat_ptr(ptr); 362 366 bufptr++; 363 367 } ··· 365 373 err = snd_pcm_lib_readv(substream, bufs, frames); 366 374 if (err >= 0) { 367 375 if (put_user(err, &data32->result)) 368 - err = -EFAULT; 376 + return -EFAULT; 369 377 } 370 - kfree(bufs); 371 378 return err; 372 379 } 373 380
+38 -61
sound/core/pcm_native.c
··· 236 236 int snd_pcm_info_user(struct snd_pcm_substream *substream, 237 237 struct snd_pcm_info __user * _info) 238 238 { 239 - struct snd_pcm_info *info; 239 + struct snd_pcm_info *info __free(kfree) = NULL; 240 240 int err; 241 241 242 242 info = kmalloc(sizeof(*info), GFP_KERNEL); ··· 247 247 if (copy_to_user(_info, info, sizeof(*info))) 248 248 err = -EFAULT; 249 249 } 250 - kfree(info); 251 250 return err; 252 251 } 253 252 ··· 358 359 struct snd_pcm_hw_constraints *constrs = 359 360 &substream->runtime->hw_constraints; 360 361 unsigned int k; 361 - unsigned int *rstamps; 362 + unsigned int *rstamps __free(kfree) = NULL; 362 363 unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; 363 364 unsigned int stamp; 364 365 struct snd_pcm_hw_rule *r; ··· 434 435 } 435 436 436 437 changed = r->func(params, r); 437 - if (changed < 0) { 438 - err = changed; 439 - goto out; 440 - } 438 + if (changed < 0) 439 + return changed; 441 440 442 441 /* 443 442 * When the parameter is changed, notify it to the caller ··· 466 469 if (again) 467 470 goto retry; 468 471 469 - out: 470 - kfree(rstamps); 471 472 return err; 472 473 } 473 474 ··· 566 571 static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, 567 572 struct snd_pcm_hw_params __user * _params) 568 573 { 569 - struct snd_pcm_hw_params *params; 574 + struct snd_pcm_hw_params *params __free(kfree) = NULL; 570 575 int err; 571 576 572 577 params = memdup_user(_params, sizeof(*params)); 573 578 if (IS_ERR(params)) 574 - return PTR_ERR(params); 579 + return PTR_ERR(no_free_ptr(params)); 575 580 576 581 err = snd_pcm_hw_refine(substream, params); 577 582 if (err < 0) 578 - goto end; 583 + return err; 579 584 580 585 err = fixup_unreferenced_params(substream, params); 581 586 if (err < 0) 582 - goto end; 587 + return err; 583 588 584 589 if (copy_to_user(_params, params, sizeof(*params))) 585 - err = -EFAULT; 586 - end: 587 - kfree(params); 588 - return err; 590 + return -EFAULT; 591 + return 0; 589 592 } 590 593 591 594 static int period_to_usecs(struct snd_pcm_runtime *runtime) ··· 857 864 static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, 858 865 struct snd_pcm_hw_params __user * _params) 859 866 { 860 - struct snd_pcm_hw_params *params; 867 + struct snd_pcm_hw_params *params __free(kfree) = NULL; 861 868 int err; 862 869 863 870 params = memdup_user(_params, sizeof(*params)); 864 871 if (IS_ERR(params)) 865 - return PTR_ERR(params); 872 + return PTR_ERR(no_free_ptr(params)); 866 873 867 874 err = snd_pcm_hw_params(substream, params); 868 875 if (err < 0) 869 - goto end; 876 + return err; 870 877 871 878 if (copy_to_user(_params, params, sizeof(*params))) 872 - err = -EFAULT; 873 - end: 874 - kfree(params); 879 + return -EFAULT; 875 880 return err; 876 881 } 877 882 ··· 2262 2271 int res = 0; 2263 2272 struct snd_pcm_file *pcm_file; 2264 2273 struct snd_pcm_substream *substream1; 2265 - struct snd_pcm_group *group, *target_group; 2274 + struct snd_pcm_group *group __free(kfree) = NULL; 2275 + struct snd_pcm_group *target_group; 2266 2276 bool nonatomic = substream->pcm->nonatomic; 2267 2277 struct fd f = fdget(fd); 2268 2278 ··· 2273 2281 res = -EBADFD; 2274 2282 goto _badf; 2275 2283 } 2284 + 2276 2285 pcm_file = f.file->private_data; 2277 2286 substream1 = pcm_file->substream; 2278 2287 ··· 2285 2292 group = kzalloc(sizeof(*group), GFP_KERNEL); 2286 2293 if (!group) { 2287 2294 res = -ENOMEM; 2288 - goto _nolock; 2295 + goto _badf; 2289 2296 } 2297 + 2290 2298 snd_pcm_group_init(group); 2291 2299 2292 2300 down_write(&snd_pcm_link_rwsem); ··· 2318 2324 snd_pcm_group_unlock_irq(target_group, nonatomic); 2319 2325 _end: 2320 2326 up_write(&snd_pcm_link_rwsem); 2321 - _nolock: 2322 - kfree(group); 2323 2327 _badf: 2324 2328 fdput(f); 2325 2329 return res; ··· 3271 3279 { 3272 3280 struct snd_xfern xfern; 3273 3281 struct snd_pcm_runtime *runtime = substream->runtime; 3274 - void *bufs; 3282 + void *bufs __free(kfree) = NULL; 3275 3283 snd_pcm_sframes_t result; 3276 3284 3277 3285 if (runtime->state == SNDRV_PCM_STATE_OPEN) ··· 3285 3293 3286 3294 bufs = memdup_user(xfern.bufs, sizeof(void *) * runtime->channels); 3287 3295 if (IS_ERR(bufs)) 3288 - return PTR_ERR(bufs); 3296 + return PTR_ERR(no_free_ptr(bufs)); 3289 3297 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 3290 3298 result = snd_pcm_lib_writev(substream, bufs, xfern.frames); 3291 3299 else 3292 3300 result = snd_pcm_lib_readv(substream, bufs, xfern.frames); 3293 - kfree(bufs); 3294 3301 if (put_user(result, &_xfern->result)) 3295 3302 return -EFAULT; 3296 3303 return result < 0 ? result : 0; ··· 3557 3566 struct snd_pcm_runtime *runtime; 3558 3567 snd_pcm_sframes_t result; 3559 3568 unsigned long i; 3560 - void __user **bufs; 3569 + void __user **bufs __free(kfree) = NULL; 3561 3570 snd_pcm_uframes_t frames; 3562 3571 const struct iovec *iov = iter_iov(to); 3563 3572 ··· 3586 3595 result = snd_pcm_lib_readv(substream, bufs, frames); 3587 3596 if (result > 0) 3588 3597 result = frames_to_bytes(runtime, result); 3589 - kfree(bufs); 3590 3598 return result; 3591 3599 } 3592 3600 ··· 3596 3606 struct snd_pcm_runtime *runtime; 3597 3607 snd_pcm_sframes_t result; 3598 3608 unsigned long i; 3599 - void __user **bufs; 3609 + void __user **bufs __free(kfree) = NULL; 3600 3610 snd_pcm_uframes_t frames; 3601 3611 const struct iovec *iov = iter_iov(from); 3602 3612 ··· 3624 3634 result = snd_pcm_lib_writev(substream, bufs, frames); 3625 3635 if (result > 0) 3626 3636 result = frames_to_bytes(runtime, result); 3627 - kfree(bufs); 3628 3637 return result; 3629 3638 } 3630 3639 ··· 4065 4076 static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, 4066 4077 struct snd_pcm_hw_params_old __user * _oparams) 4067 4078 { 4068 - struct snd_pcm_hw_params *params; 4069 - struct snd_pcm_hw_params_old *oparams = NULL; 4079 + struct snd_pcm_hw_params *params __free(kfree) = NULL; 4080 + struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL; 4070 4081 int err; 4071 4082 4072 4083 params = kmalloc(sizeof(*params), GFP_KERNEL); ··· 4074 4085 return -ENOMEM; 4075 4086 4076 4087 oparams = memdup_user(_oparams, sizeof(*oparams)); 4077 - if (IS_ERR(oparams)) { 4078 - err = PTR_ERR(oparams); 4079 - goto out; 4080 - } 4088 + if (IS_ERR(oparams)) 4089 + return PTR_ERR(no_free_ptr(oparams)); 4081 4090 snd_pcm_hw_convert_from_old_params(params, oparams); 4082 4091 err = snd_pcm_hw_refine(substream, params); 4083 4092 if (err < 0) 4084 - goto out_old; 4093 + return err; 4085 4094 4086 4095 err = fixup_unreferenced_params(substream, params); 4087 4096 if (err < 0) 4088 - goto out_old; 4097 + return err; 4089 4098 4090 4099 snd_pcm_hw_convert_to_old_params(oparams, params); 4091 4100 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) 4092 - err = -EFAULT; 4093 - out_old: 4094 - kfree(oparams); 4095 - out: 4096 - kfree(params); 4097 - return err; 4101 + return -EFAULT; 4102 + return 0; 4098 4103 } 4099 4104 4100 4105 static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, 4101 4106 struct snd_pcm_hw_params_old __user * _oparams) 4102 4107 { 4103 - struct snd_pcm_hw_params *params; 4104 - struct snd_pcm_hw_params_old *oparams = NULL; 4108 + struct snd_pcm_hw_params *params __free(kfree) = NULL; 4109 + struct snd_pcm_hw_params_old *oparams __free(kfree) = NULL; 4105 4110 int err; 4106 4111 4107 4112 params = kmalloc(sizeof(*params), GFP_KERNEL); ··· 4103 4120 return -ENOMEM; 4104 4121 4105 4122 oparams = memdup_user(_oparams, sizeof(*oparams)); 4106 - if (IS_ERR(oparams)) { 4107 - err = PTR_ERR(oparams); 4108 - goto out; 4109 - } 4123 + if (IS_ERR(oparams)) 4124 + return PTR_ERR(no_free_ptr(oparams)); 4110 4125 4111 4126 snd_pcm_hw_convert_from_old_params(params, oparams); 4112 4127 err = snd_pcm_hw_params(substream, params); 4113 4128 if (err < 0) 4114 - goto out_old; 4129 + return err; 4115 4130 4116 4131 snd_pcm_hw_convert_to_old_params(oparams, params); 4117 4132 if (copy_to_user(_oparams, oparams, sizeof(*oparams))) 4118 - err = -EFAULT; 4119 - out_old: 4120 - kfree(oparams); 4121 - out: 4122 - kfree(params); 4123 - return err; 4133 + return -EFAULT; 4134 + return 0; 4124 4135 } 4125 4136 #endif /* CONFIG_SND_SUPPORT_OLD_API */ 4126 4137