ALSA: emux: improve patch ioctl data validation
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>
Sat, 6 Apr 2024 06:48:20 +0000 (08:48 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sun, 7 Apr 2024 06:35:48 +0000 (08:35 +0200)
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>
sound/synth/emux/soundfont.c

index 6d6f0102ed5b920f30f55a4c7fcb83ec1845a56b..4edc693da8e74120c00d81e124ca4ec4e623c0b1 100644 (file)
@@ -716,7 +716,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;
@@ -726,12 +725,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 */
@@ -774,7 +777,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;
@@ -986,10 +989,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count)
        }
        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;