Patch "ALSA: pcm: Fix potential data race at PCM memory allocation helpers" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ALSA: pcm: Fix potential data race at PCM memory allocation helpers

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     alsa-pcm-fix-potential-data-race-at-pcm-memory-alloc.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 1e1e845af20e7af462dac1f6ca891de24b59c6d8
Author: Takashi Iwai <tiwai@xxxxxxx>
Date:   Mon Jul 3 13:24:30 2023 +0200

    ALSA: pcm: Fix potential data race at PCM memory allocation helpers
    
    [ Upstream commit bd55842ed998a622ba6611fe59b3358c9f76773d ]
    
    The PCM memory allocation helpers have a sanity check against too many
    buffer allocations.  However, the check is performed without a proper
    lock and the allocation isn't serialized; this allows user to allocate
    more memories than predefined max size.
    
    Practically seen, this isn't really a big problem, as it's more or
    less some "soft limit" as a sanity check, and it's not possible to
    allocate unlimitedly.  But it's still better to address this for more
    consistent behavior.
    
    The patch covers the size check in do_alloc_pages() with the
    card->memory_mutex, and increases the allocated size there for
    preventing the further overflow.  When the actual allocation fails,
    the size is decreased accordingly.
    
    Reported-by: BassCheck <bass@xxxxxxxxxxx>
    Reported-by: Tuo Li <islituo@xxxxxxxxx>
    Link: https://lore.kernel.org/r/CADm8Tek6t0WedK+3Y6rbE5YEt19tML8BUL45N2ji4ZAz1KcN_A@xxxxxxxxxxxxxx
    Reviewed-by: Jaroslav Kysela <perex@xxxxxxxx>
    Cc: <stable@xxxxxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230703112430.30634-1-tiwai@xxxxxxx
    Signed-off-by: Takashi Iwai <tiwai@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 97b471d7b32e5..beca39f7c8f35 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -31,14 +31,40 @@ static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
 module_param(max_alloc_per_card, ulong, 0644);
 MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
 
+static void __update_allocated_size(struct snd_card *card, ssize_t bytes)
+{
+	card->total_pcm_alloc_bytes += bytes;
+}
+
+static void update_allocated_size(struct snd_card *card, ssize_t bytes)
+{
+	mutex_lock(&card->memory_mutex);
+	__update_allocated_size(card, bytes);
+	mutex_unlock(&card->memory_mutex);
+}
+
+static void decrease_allocated_size(struct snd_card *card, size_t bytes)
+{
+	mutex_lock(&card->memory_mutex);
+	WARN_ON(card->total_pcm_alloc_bytes < bytes);
+	__update_allocated_size(card, -(ssize_t)bytes);
+	mutex_unlock(&card->memory_mutex);
+}
+
 static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
 			  size_t size, struct snd_dma_buffer *dmab)
 {
 	int err;
 
+	/* check and reserve the requested size */
+	mutex_lock(&card->memory_mutex);
 	if (max_alloc_per_card &&
-	    card->total_pcm_alloc_bytes + size > max_alloc_per_card)
+	    card->total_pcm_alloc_bytes + size > max_alloc_per_card) {
+		mutex_unlock(&card->memory_mutex);
 		return -ENOMEM;
+	}
+	__update_allocated_size(card, size);
+	mutex_unlock(&card->memory_mutex);
 
 	if (IS_ENABLED(CONFIG_SND_DMA_SGBUF) &&
 	    (type == SNDRV_DMA_TYPE_DEV_SG || type == SNDRV_DMA_TYPE_DEV_UC_SG) &&
@@ -53,9 +79,14 @@ static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
 
 	err = snd_dma_alloc_pages(type, dev, size, dmab);
 	if (!err) {
-		mutex_lock(&card->memory_mutex);
-		card->total_pcm_alloc_bytes += dmab->bytes;
-		mutex_unlock(&card->memory_mutex);
+		/* the actual allocation size might be bigger than requested,
+		 * and we need to correct the account
+		 */
+		if (dmab->bytes != size)
+			update_allocated_size(card, dmab->bytes - size);
+	} else {
+		/* take back on allocation failure */
+		decrease_allocated_size(card, size);
 	}
 	return err;
 }
@@ -64,10 +95,7 @@ static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
 {
 	if (!dmab->area)
 		return;
-	mutex_lock(&card->memory_mutex);
-	WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes);
-	card->total_pcm_alloc_bytes -= dmab->bytes;
-	mutex_unlock(&card->memory_mutex);
+	decrease_allocated_size(card, dmab->bytes);
 	snd_dma_free_pages(dmab);
 	dmab->area = NULL;
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux