Commit 084d5d44 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: mixer: oss: Add card disconnect checkpoints

ALSA OSS mixer layer calls the kcontrol ops rather individually, and
pending calls might be not always caught at disconnecting the device.

For avoiding the potential UAF scenarios, add sanity checks of the
card disconnection at each entry point of OSS mixer accesses.  The
rwsem is taken just before that check, hence the rest context should
be covered by that properly.

Link: https://patch.msgid.link/20260209121212.171430-1-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent ac656d7d
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -523,6 +523,8 @@ static void snd_mixer_oss_get_volume1_vol(struct snd_mixer_oss_file *fmixer,
	if (numid == ID_UNKNOWN)
		return;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return;
	kctl = snd_ctl_find_numid(card, numid);
	if (!kctl)
		return;
@@ -557,6 +559,8 @@ static void snd_mixer_oss_get_volume1_sw(struct snd_mixer_oss_file *fmixer,
	if (numid == ID_UNKNOWN)
		return;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return;
	kctl = snd_ctl_find_numid(card, numid);
	if (!kctl)
		return;
@@ -618,6 +622,8 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
	if (numid == ID_UNKNOWN)
		return;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return;
	kctl = snd_ctl_find_numid(card, numid);
	if (!kctl)
		return;
@@ -656,6 +662,8 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
	if (numid == ID_UNKNOWN)
		return;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return;
	kctl = snd_ctl_find_numid(card, numid);
	if (!kctl)
		return;
@@ -796,6 +804,8 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
	if (uinfo == NULL || uctl == NULL)
		return -ENOMEM;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return -ENODEV;
	kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
	if (!kctl)
		return -ENOENT;
@@ -839,6 +849,8 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
	if (uinfo == NULL || uctl == NULL)
		return -ENOMEM;
	guard(rwsem_read)(&card->controls_rwsem);
	if (card->shutdown)
		return -ENODEV;
	kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
	if (!kctl)
		return -ENOENT;
@@ -885,6 +897,8 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
	if (!info)
		return -ENOMEM;
	scoped_guard(rwsem_read, &card->controls_rwsem) {
		if (card->shutdown)
			return -ENODEV;
		kcontrol = snd_mixer_oss_test_id(mixer, name, index);
		if (kcontrol == NULL)
			return 0;
@@ -1006,6 +1020,8 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
	if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
		return 0;
	guard(rwsem_read)(&mixer->card->controls_rwsem);
	if (mixer->card->shutdown)
		return -ENODEV;
	kctl = NULL;
	if (!ptr->index)
		kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);