Unverified Commit 0fae253a authored by Pierre-Louis Bossart's avatar Pierre-Louis Bossart Committed by Mark Brown
Browse files

ASoC: soc-devres: add devm_snd_soc_register_dai()



The registration of DAIs may be done at two distinct times, once
during a component registration and later when loading a
topology. Since devm_ managed resources are freed in the reverse order
they were allocated, when a component starts unregistering DAIs by
walking through the DAI list, the memory allocated for the
topology-registered DAIs was freed already, which leads to 100%
reproducible KASAN use-after-free reports.

This patch suggests a new devm_ function to force the DAI list to be
updated prior to freeing the memory chunks referenced by the list
pointers.

Suggested-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
BugLink: https://github.com/thesofproject/linux/issues/2186
Link: https://lore.kernel.org/r/20200612205938.26415-2-pierre-louis.bossart@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent b287a6d9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1363,6 +1363,10 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component,
					 struct snd_soc_dai_driver *dai_drv,
					 bool legacy_dai_naming);
struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
					      struct snd_soc_component *component,
					      struct snd_soc_dai_driver *dai_drv,
					      bool legacy_dai_naming);
void snd_soc_unregister_dai(struct snd_soc_dai *dai);

struct snd_soc_dai *snd_soc_find_dai(
+37 −0
Original line number Diff line number Diff line
@@ -9,6 +9,43 @@
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>

static void devm_dai_release(struct device *dev, void *res)
{
	snd_soc_unregister_dai(*(struct snd_soc_dai **)res);
}

/**
 * devm_snd_soc_register_dai - resource-managed dai registration
 * @dev: Device used to manage component
 * @component: The component the DAIs are registered for
 * @dai_drv: DAI driver to use for the DAI
 * @legacy_dai_naming: if %true, use legacy single-name format;
 *	if %false, use multiple-name format;
 */
struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev,
					      struct snd_soc_component *component,
					      struct snd_soc_dai_driver *dai_drv,
					      bool legacy_dai_naming)
{
	struct snd_soc_dai **ptr;
	struct snd_soc_dai *dai;

	ptr = devres_alloc(devm_dai_release, sizeof(*ptr), GFP_KERNEL);
	if (!ptr)
		return NULL;

	dai = snd_soc_register_dai(component, dai_drv, legacy_dai_naming);
	if (dai) {
		*ptr = dai;
		devres_add(dev, ptr);
	} else {
		devres_free(ptr);
	}

	return dai;
}
EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai);

static void devm_component_release(struct device *dev, void *res)
{
	snd_soc_unregister_component(*(struct device **)res);