diff mbox series

[RFC,3/6] ALSA: core: Associate memory reference with device initialization

Message ID 20230807135207.17708-5-tiwai@suse.de
State New
Headers show
Series ALSA: Fix UAF with delayed kobj release | expand

Commit Message

Takashi Iwai Aug. 7, 2023, 1:52 p.m. UTC
Allow to assign a refmem pointer to snd_device_initialize().  It takes
the reference, and does unreference at the release callback in turn.

A caveat is that this uses drvdata for keeping the associated
pointer.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/core.h           | 2 +-
 sound/core/compress_offload.c  | 2 +-
 sound/core/control.c           | 2 +-
 sound/core/hwdep.c             | 2 +-
 sound/core/init.c              | 9 ++++++---
 sound/core/pcm.c               | 2 +-
 sound/core/rawmidi.c           | 2 +-
 sound/core/seq/seq_clientmgr.c | 2 +-
 sound/core/timer.c             | 2 +-
 9 files changed, 14 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/include/sound/core.h b/include/sound/core.h
index 6fccec08a12f..dfa5b44d9666 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -244,7 +244,7 @@  extern struct dentry *sound_debugfs_root;
 
 void snd_request_card(int card);
 
-void snd_device_initialize(struct device *dev, struct snd_card *card);
+void snd_device_initialize(struct device *dev, struct snd_card *card, void *refp);
 
 int snd_register_device(int type, struct snd_card *card, int dev,
 			const struct file_operations *f_ops,
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 30f73097447b..d91fa8925cde 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1189,7 +1189,7 @@  int snd_compress_new(struct snd_card *card, int device,
 
 	snd_compress_set_id(compr, id);
 
-	snd_device_initialize(&compr->dev, card);
+	snd_device_initialize(&compr->dev, card, NULL);
 	dev_set_name(&compr->dev, "comprC%iD%i", card->number, device);
 
 	ret = snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
diff --git a/sound/core/control.c b/sound/core/control.c
index 8386b53acdcd..5b9340f5cb8c 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -2395,7 +2395,7 @@  int snd_ctl_create(struct snd_card *card)
 	if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS))
 		return -ENXIO;
 
-	snd_device_initialize(&card->ctl_dev, card);
+	snd_device_initialize(&card->ctl_dev, card, NULL);
 	dev_set_name(&card->ctl_dev, "controlC%d", card->number);
 
 	err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index e95fa275c289..5edea1094a07 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -382,7 +382,7 @@  int snd_hwdep_new(struct snd_card *card, char *id, int device,
 	if (id)
 		strscpy(hwdep->id, id, sizeof(hwdep->id));
 
-	snd_device_initialize(&hwdep->dev, card);
+	snd_device_initialize(&hwdep->dev, card, NULL);
 	hwdep->dev.release = release_hwdep_device;
 	dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device);
 #ifdef CONFIG_SND_OSSEMUL
diff --git a/sound/core/init.c b/sound/core/init.c
index 22da438faf40..6bc77705ecc3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -170,25 +170,28 @@  void snd_refmem_put(void *p)
 EXPORT_SYMBOL_GPL(snd_refmem_put);
 
 /* the default release callback set in snd_device_initialize() below;
- * this is just NOP for now, as almost all jobs are already done in
- * dev_free callback of snd_device chain instead.
+ * unreference the memory here if it's specified at initialization
  */
 static void default_release(struct device *dev)
 {
+	snd_refmem_put(dev_get_drvdata(dev));
 }
 
 /**
  * snd_device_initialize - Initialize struct device for sound devices
  * @dev: device to initialize
  * @card: card to assign, optional
+ * @refp: memory associated with snd_refmem
  */
-void snd_device_initialize(struct device *dev, struct snd_card *card)
+void snd_device_initialize(struct device *dev, struct snd_card *card, void *refp)
 {
 	device_initialize(dev);
 	if (card)
 		dev->parent = &card->card_dev;
 	dev->class = &sound_class;
 	dev->release = default_release;
+	dev_set_drvdata(dev, refp);
+	snd_refmem_get(refp);
 }
 EXPORT_SYMBOL_GPL(snd_device_initialize);
 
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9d95e3731123..461a10cc0db9 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -650,7 +650,7 @@  int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 	if (!substream_count)
 		return 0;
 
-	snd_device_initialize(&pstr->dev, pcm->card);
+	snd_device_initialize(&pstr->dev, pcm->card, NULL);
 	pstr->dev.groups = pcm_dev_attr_groups;
 	pstr->dev.type = &pcm_dev_type;
 	dev_set_name(&pstr->dev, "pcmC%iD%i%c", pcm->card->number, pcm->device,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 2d3cec908154..34f124b126ca 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1906,7 +1906,7 @@  int snd_rawmidi_init(struct snd_rawmidi *rmidi,
 	if (id != NULL)
 		strscpy(rmidi->id, id, sizeof(rmidi->id));
 
-	snd_device_initialize(&rmidi->dev, card);
+	snd_device_initialize(&rmidi->dev, card, NULL);
 	rmidi->dev.release = release_rawmidi_device;
 	if (rawmidi_is_ump(rmidi))
 		dev_set_name(&rmidi->dev, "umpC%iD%i", card->number, device);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index e3f9ea67d019..66e73b35e57e 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -2730,7 +2730,7 @@  int __init snd_sequencer_device_init(void)
 {
 	int err;
 
-	snd_device_initialize(&seq_dev, NULL);
+	snd_device_initialize(&seq_dev, NULL, NULL);
 	dev_set_name(&seq_dev, "seq");
 
 	mutex_lock(&register_mutex);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 9d0d2a5c2e15..04e77a89ecb6 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -2311,7 +2311,7 @@  static int __init alsa_timer_init(void)
 {
 	int err;
 
-	snd_device_initialize(&timer_dev, NULL);
+	snd_device_initialize(&timer_dev, NULL, NULL);
 	dev_set_name(&timer_dev, "timer");
 
 #ifdef SNDRV_OSS_INFO_DEV_TIMERS