diff mbox series

SOF: Intel: hda: fix memory leak in hda_machine_select()

Message ID 20241126144145.4442-1-dmantipov@yandex.ru (mailing list archive)
State Superseded
Headers show
Series SOF: Intel: hda: fix memory leak in hda_machine_select() | expand

Commit Message

Dmitry Antipov Nov. 26, 2024, 2:41 p.m. UTC
Kernel memory leak detector has reported the following leak:

unreferenced object 0xffff88810f54bed0 (size 16):
  comm "kworker/18:1", pid 162, jiffies 4294754593
  hex dump (first 16 bytes):
    73 6f 66 2d 68 64 61 2d 67 65 6e 65 72 69 63 00  sof-hda-generic.
  backtrace (crc 4bf1675c):
    [<00000000c0f2b5a4>] __kmalloc_node_track_caller_noprof+0x349/0x610
    [<000000008c0a621c>] kstrdup+0x3d/0x70
    [<0000000036666329>] hda_machine_select+0xbe0/0x1e60 [snd_sof_intel_hda_generic]
    [<00000000f9312d18>] sof_probe_work+0x192/0x1bc0 [snd_sof]
    [<00000000e86720cf>] process_scheduled_works+0x7ab/0xe80
    [<000000006ac5a4f7>] worker_thread+0x9b2/0xda0
    [<00000000bb5178a6>] kthread+0x260/0x310
    [<0000000045bf5f63>] ret_from_fork+0x45/0x80
    [<0000000064567ca7>] ret_from_fork_asm+0x1a/0x30

This happens when kstrdup()'ed area returned by 'remove_file_ext()' becomes
unreferenced after assigning new value to 'sof_pdata->tplg_filename'. Since
an explicit management of this area with 'kfree()' may be annoying and
error-prone, tweak 'remove_file_ext()' to use 'devm_kmalloc()' (and so
use memory which is automatically freed on driver detach).

Fixes: 85b66359c5a7 ("ASoC: SOF: Intel: hda: refactoring topology name fixup for SDW mach")
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
 sound/soc/sof/intel/hda.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 01b135068b1f..a72f62f4e6cf 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1197,16 +1197,17 @@  static int check_tplg_quirk_mask(struct snd_soc_acpi_mach *mach)
 	return 0;
 }
 
-static char *remove_file_ext(const char *tplg_filename)
+static char *remove_file_ext(struct device *dev, const char *tplg_filename)
 {
 	char *filename, *tmp;
+	size_t len = strlen(tplg_filename);
 
-	filename = kstrdup(tplg_filename, GFP_KERNEL);
+	filename = devm_kmalloc(dev, len + 1, GFP_KERNEL);
 	if (!filename)
 		return NULL;
 
 	/* remove file extension if exist */
-	tmp = filename;
+	tmp = memcpy(filename, tplg_filename, len + 1);
 	return strsep(&tmp, ".");
 }
 
@@ -1285,7 +1286,7 @@  struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev)
 		 */
 		if (!sof_pdata->tplg_filename) {
 			/* remove file extension if it exists */
-			tplg_filename = remove_file_ext(mach->sof_tplg_filename);
+			tplg_filename = remove_file_ext(sdev->dev, mach->sof_tplg_filename);
 			if (!tplg_filename)
 				return NULL;