]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ALSA: emux: improve patch ioctl data validation
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Sat, 6 Apr 2024 06:48:20 +0000 (08:48 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 5 Jul 2024 07:37:59 +0000 (09:37 +0200)
[ Upstream commit 89b32ccb12ae67e630c6453d778ec30a592a212f ]

In load_data(), make the validation of and skipping over the main info
block match that in load_guspatch().

In load_guspatch(), add checking that the specified patch length matches
the actually supplied data, like load_data() already did.

Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Message-ID: <20240406064830.1029573-8-oswald.buddenhagen@gmx.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
sound/synth/emux/soundfont.c

index 16f00097cb95a87bec0e75077ca1928dbae5d407..eed47e48302485c9a12f204c33d334b6d15305f0 100644 (file)
@@ -701,7 +701,6 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
        struct snd_soundfont *sf;
        struct soundfont_sample_info sample_info;
        struct snd_sf_sample *sp;
-       long off;
 
        /* patch must be opened */
        sf = sflist->currsf;
@@ -711,12 +710,16 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
        if (is_special_type(sf->type))
                return -EINVAL;
 
+       if (count < (long)sizeof(sample_info)) {
+               return -EINVAL;
+       }
        if (copy_from_user(&sample_info, data, sizeof(sample_info)))
                return -EFAULT;
+       data += sizeof(sample_info);
+       count -= sizeof(sample_info);
 
-       off = sizeof(sample_info);
-
-       if (sample_info.size != (count-off)/2)
+       // SoundFont uses S16LE samples.
+       if (sample_info.size * 2 != count)
                return -EINVAL;
 
        /* Check for dup */
@@ -744,7 +747,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
                int  rc;
                rc = sflist->callback.sample_new
                        (sflist->callback.private_data, sp, sflist->memhdr,
-                        data + off, count - off);
+                        data, count);
                if (rc < 0) {
                        sf_sample_delete(sflist, sf, sp);
                        return rc;
@@ -957,10 +960,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
        }
        if (copy_from_user(&patch, data, sizeof(patch)))
                return -EFAULT;
-       
        count -= sizeof(patch);
        data += sizeof(patch);
 
+       if ((patch.len << (patch.mode & WAVE_16_BITS ? 1 : 0)) != count)
+               return -EINVAL;
+
        sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL);
        if (sf == NULL)
                return -ENOMEM;