From bee569b89401d57904291546a549c4c5914dff0d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Apr 2024 10:36:47 +0200 Subject: [PATCH] 5.10-stable patches added patches: alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch --- ...cleanup-operations-to-avoid-uaf-bugs.patch | 95 +++++++++++++++++++ queue-5.10/series | 1 + 2 files changed, 96 insertions(+) create mode 100644 queue-5.10/alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch diff --git a/queue-5.10/alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch b/queue-5.10/alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch new file mode 100644 index 00000000000..88af141cb4b --- /dev/null +++ b/queue-5.10/alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch @@ -0,0 +1,95 @@ +From 051e0840ffa8ab25554d6b14b62c9ab9e4901457 Mon Sep 17 00:00:00 2001 +From: Duoming Zhou +Date: Tue, 26 Mar 2024 17:42:38 +0800 +Subject: ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs + +From: Duoming Zhou + +commit 051e0840ffa8ab25554d6b14b62c9ab9e4901457 upstream. + +The dreamcastcard->timer could schedule the spu_dma_work and the +spu_dma_work could also arm the dreamcastcard->timer. + +When the snd_pcm_substream is closing, the aica_channel will be +deallocated. But it could still be dereferenced in the worker +thread. The reason is that del_timer() will return directly +regardless of whether the timer handler is running or not and +the worker could be rescheduled in the timer handler. As a result, +the UAF bug will happen. The racy situation is shown below: + + (Thread 1) | (Thread 2) +snd_aicapcm_pcm_close() | + ... | run_spu_dma() //worker + | mod_timer() + flush_work() | + del_timer() | aica_period_elapsed() //timer + kfree(dreamcastcard->channel) | schedule_work() + | run_spu_dma() //worker + ... | dreamcastcard->channel-> //USE + +In order to mitigate this bug and other possible corner cases, +call mod_timer() conditionally in run_spu_dma(), then implement +PCM sync_stop op to cancel both the timer and worker. The sync_stop +op will be called from PCM core appropriately when needed. + +Fixes: 198de43d758c ("[ALSA] Add ALSA support for the SEGA Dreamcast PCM device") +Suggested-by: Takashi Iwai +Signed-off-by: Duoming Zhou +Message-ID: <20240326094238.95442-1-duoming@zju.edu.cn> +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/sh/aica.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/sound/sh/aica.c ++++ b/sound/sh/aica.c +@@ -279,7 +279,8 @@ static void run_spu_dma(struct work_stru + dreamcastcard->clicks++; + if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER)) + dreamcastcard->clicks %= AICA_PERIOD_NUMBER; +- mod_timer(&dreamcastcard->timer, jiffies + 1); ++ if (snd_pcm_running(dreamcastcard->substream)) ++ mod_timer(&dreamcastcard->timer, jiffies + 1); + } + } + +@@ -291,6 +292,8 @@ static void aica_period_elapsed(struct t + /*timer function - so cannot sleep */ + int play_period; + struct snd_pcm_runtime *runtime; ++ if (!snd_pcm_running(substream)) ++ return; + runtime = substream->runtime; + dreamcastcard = substream->pcm->private_data; + /* Have we played out an additional period? */ +@@ -351,12 +354,19 @@ static int snd_aicapcm_pcm_open(struct s + return 0; + } + ++static int snd_aicapcm_pcm_sync_stop(struct snd_pcm_substream *substream) ++{ ++ struct snd_card_aica *dreamcastcard = substream->pcm->private_data; ++ ++ del_timer_sync(&dreamcastcard->timer); ++ cancel_work_sync(&dreamcastcard->spu_dma_work); ++ return 0; ++} ++ + static int snd_aicapcm_pcm_close(struct snd_pcm_substream + *substream) + { + struct snd_card_aica *dreamcastcard = substream->pcm->private_data; +- flush_work(&(dreamcastcard->spu_dma_work)); +- del_timer(&dreamcastcard->timer); + dreamcastcard->substream = NULL; + kfree(dreamcastcard->channel); + spu_disable(); +@@ -402,6 +412,7 @@ static const struct snd_pcm_ops snd_aica + .prepare = snd_aicapcm_pcm_prepare, + .trigger = snd_aicapcm_pcm_trigger, + .pointer = snd_aicapcm_pcm_pointer, ++ .sync_stop = snd_aicapcm_pcm_sync_stop, + }; + + /* TO DO: set up to handle more than one pcm instance */ diff --git a/queue-5.10/series b/queue-5.10/series index c00ab71ff95..5f7180b5c79 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -160,3 +160,4 @@ mmc-core-initialize-mmc_blk_ioc_data.patch mmc-core-avoid-negative-index-with-array-access.patch net-ll_temac-platform_get_resource-replaced-by-wrong-function.patch usb-cdc-wdm-close-race-between-read-and-workqueue.patch +alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch -- 2.47.2