diff options
Diffstat (limited to 'sound/core/init.c')
| -rw-r--r-- | sound/core/init.c | 28 | 
1 files changed, 28 insertions, 0 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index 31ba7024e3ad..726a8353201f 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -209,6 +209,12 @@ static void __snd_card_release(struct device *dev, void *data)   * snd_card_register(), the very first devres action to call snd_card_free()   * is added automatically.  In that way, the resource disconnection is assured   * at first, then released in the expected order. + * + * If an error happens at the probe before snd_card_register() is called and + * there have been other devres resources, you'd need to free the card manually + * via snd_card_free() call in the error; otherwise it may lead to UAF due to + * devres call orders.  You can use snd_card_free_on_error() helper for + * handling it more easily.   */  int snd_devm_card_new(struct device *parent, int idx, const char *xid,  		      struct module *module, size_t extra_size, @@ -235,6 +241,28 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,  }  EXPORT_SYMBOL_GPL(snd_devm_card_new); +/** + * snd_card_free_on_error - a small helper for handling devm probe errors + * @dev: the managed device object + * @ret: the return code from the probe callback + * + * This function handles the explicit snd_card_free() call at the error from + * the probe callback.  It's just a small helper for simplifying the error + * handling with the managed devices. + */ +int snd_card_free_on_error(struct device *dev, int ret) +{ +	struct snd_card *card; + +	if (!ret) +		return 0; +	card = devres_find(dev, __snd_card_release, NULL, NULL); +	if (card) +		snd_card_free(card); +	return ret; +} +EXPORT_SYMBOL_GPL(snd_card_free_on_error); +  static int snd_card_init(struct snd_card *card, struct device *parent,  			 int idx, const char *xid, struct module *module,  			 size_t extra_size)  |