summaryrefslogtreecommitdiffstats
path: root/sound/synth
diff options
context:
space:
mode:
Diffstat (limited to 'sound/synth')
-rw-r--r--sound/synth/Makefile2
-rw-r--r--sound/synth/emux/Makefile2
-rw-r--r--sound/synth/emux/emux.c6
-rw-r--r--sound/synth/emux/emux_hwdep.c3
-rw-r--r--sound/synth/emux/emux_oss.c3
-rw-r--r--sound/synth/emux/emux_proc.c1
-rw-r--r--sound/synth/emux/emux_seq.c6
-rw-r--r--sound/synth/emux/soundfont.c73
8 files changed, 65 insertions, 31 deletions
diff --git a/sound/synth/Makefile b/sound/synth/Makefile
index b9f71d5dbc8c..369f3be2cd17 100644
--- a/sound/synth/Makefile
+++ b/sound/synth/Makefile
@@ -4,7 +4,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
-snd-util-mem-objs := util_mem.o
+snd-util-mem-y := util_mem.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_EMU10K1) += snd-util-mem.o
diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile
index ed28c81ac12e..59357da6d1ef 100644
--- a/sound/synth/emux/Makefile
+++ b/sound/synth/emux/Makefile
@@ -4,7 +4,7 @@
# Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
#
-snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \
+snd-emux-synth-y := emux.o emux_synth.o emux_seq.o emux_nrpn.o \
emux_effect.o emux_hwdep.o soundfont.o
snd-emux-synth-$(CONFIG_SND_PROC_FS) += emux_proc.o
ifneq ($(CONFIG_SND_SEQUENCER_OSS),)
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index a82af9374852..01444fc960d0 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -94,10 +94,8 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch
/* create soundfont list */
memset(&sf_cb, 0, sizeof(sf_cb));
sf_cb.private_data = emu;
- if (emu->ops.sample_new)
- sf_cb.sample_new = sf_sample_new;
- if (emu->ops.sample_free)
- sf_cb.sample_free = sf_sample_free;
+ sf_cb.sample_new = sf_sample_new;
+ sf_cb.sample_free = sf_sample_free;
if (emu->ops.sample_reset)
sf_cb.sample_reset = sf_sample_reset;
emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index 81719bfb8ed7..fd8f978cde1c 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -27,8 +27,7 @@ snd_emux_hwdep_load_patch(struct snd_emux *emu, void __user *arg)
if (patch.key == GUS_PATCH)
return snd_soundfont_load_guspatch(emu->sflist, arg,
- patch.len + sizeof(patch),
- TMP_CLIENT_ID);
+ patch.len + sizeof(patch));
if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
patch.type <= SNDRV_SFNT_PROBE_DATA) {
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index d8d32671f703..04df46b269d3 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -205,8 +205,7 @@ snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
return -ENXIO;
if (format == GUS_PATCH)
- rc = snd_soundfont_load_guspatch(emu->sflist, buf, count,
- SF_CLIENT_NO(p->chset.port));
+ rc = snd_soundfont_load_guspatch(emu->sflist, buf, count);
else if (format == SNDRV_OSS_SOUNDFONT_PATCH) {
struct soundfont_patch_info patch;
if (count < (int)sizeof(patch))
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index 7993e6a01e54..820351f52551 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -102,6 +102,7 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device)
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = emu;
entry->c.text.read = snd_emux_proc_info_read;
+ emu->proc = entry;
}
void snd_emux_proc_free(struct snd_emux *emu)
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index b227c7e0bc2a..1adaa75df2f6 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -65,11 +65,11 @@ snd_emux_init_seq(struct snd_emux *emu, struct snd_card *card, int index)
return -ENODEV;
}
- if (emu->num_ports < 0) {
+ if (emu->num_ports <= 0) {
snd_printk(KERN_WARNING "seqports must be greater than zero\n");
emu->num_ports = 1;
- } else if (emu->num_ports >= SNDRV_EMUX_MAX_PORTS) {
- snd_printk(KERN_WARNING "too many ports."
+ } else if (emu->num_ports > SNDRV_EMUX_MAX_PORTS) {
+ snd_printk(KERN_WARNING "too many ports. "
"limited max. ports %d\n", SNDRV_EMUX_MAX_PORTS);
emu->num_ports = SNDRV_EMUX_MAX_PORTS;
}
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 16f00097cb95..2373ed580bf8 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -689,6 +689,21 @@ find_sample(struct snd_soundfont *sf, int sample_id)
}
+static int
+validate_sample_info(struct soundfont_sample_info *si)
+{
+ if (si->end < 0 || si->end > si->size)
+ return -EINVAL;
+ if (si->loopstart < 0 || si->loopstart > si->end)
+ return -EINVAL;
+ if (si->loopend < 0 || si->loopend > si->end)
+ return -EINVAL;
+ /* be sure loop points start < end */
+ if (si->loopstart > si->loopend)
+ swap(si->loopstart, si->loopend);
+ return 0;
+}
+
/*
* Load sample information, this can include data to be loaded onto
* the soundcard. It can also just be a pointer into soundcard ROM.
@@ -701,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;
@@ -711,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 */
@@ -727,6 +745,21 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
return -EINVAL;
}
+ if (sample_info.size > 0) {
+ if (sample_info.start < 0)
+ return -EINVAL;
+
+ // Here we "rebase out" the start address, because the
+ // real start is the start of the provided sample data.
+ sample_info.end -= sample_info.start;
+ sample_info.loopstart -= sample_info.start;
+ sample_info.loopend -= sample_info.start;
+ sample_info.start = 0;
+
+ if (validate_sample_info(&sample_info) < 0)
+ return -EINVAL;
+ }
+
/* Allocate a new sample structure */
sp = sf_sample_new(sflist, sf);
if (!sp)
@@ -735,7 +768,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
sp->v = sample_info;
sp->v.sf_id = sf->id;
sp->v.dummy = 0;
- sp->v.truesize = sp->v.size;
+ sp->v.truesize = 0;
/*
* If there is wave data then load it.
@@ -744,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;
@@ -941,8 +974,7 @@ int snd_sf_vol_table[128] = {
/* load GUS patch */
static int
-load_guspatch(struct snd_sf_list *sflist, const char __user *data,
- long count, int client)
+load_guspatch(struct snd_sf_list *sflist, const char __user *data, long count)
{
struct patch_info patch;
struct snd_soundfont *sf;
@@ -957,10 +989,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;
@@ -975,6 +1009,11 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
smp->v.loopend = patch.loop_end;
smp->v.size = patch.len;
+ if (validate_sample_info(&smp->v) < 0) {
+ sf_sample_delete(sflist, sf, smp);
+ return -EINVAL;
+ }
+
/* set up mode flags */
smp->v.mode_flags = 0;
if (!(patch.mode & WAVE_16_BITS))
@@ -1012,7 +1051,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
/*
* load wave data
*/
- if (sflist->callback.sample_new) {
+ if (smp->v.size > 0) {
rc = sflist->callback.sample_new
(sflist->callback.private_data, smp, sflist->memhdr,
data, count);
@@ -1122,11 +1161,11 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data,
/* load GUS patch */
int
snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data,
- long count, int client)
+ long count)
{
int rc;
lock_preset(sflist);
- rc = load_guspatch(sflist, data, count, client);
+ rc = load_guspatch(sflist, data, count);
unlock_preset(sflist);
return rc;
}
@@ -1377,9 +1416,8 @@ snd_sf_clear(struct snd_sf_list *sflist)
}
for (sp = sf->samples; sp; sp = nextsp) {
nextsp = sp->next;
- if (sflist->callback.sample_free)
- sflist->callback.sample_free(sflist->callback.private_data,
- sp, sflist->memhdr);
+ sflist->callback.sample_free(sflist->callback.private_data,
+ sp, sflist->memhdr);
kfree(sp);
}
kfree(sf);
@@ -1481,9 +1519,8 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist)
nextsp = sp->next;
sf->samples = nextsp;
sflist->mem_used -= sp->v.truesize;
- if (sflist->callback.sample_free)
- sflist->callback.sample_free(sflist->callback.private_data,
- sp, sflist->memhdr);
+ sflist->callback.sample_free(sflist->callback.private_data,
+ sp, sflist->memhdr);
kfree(sp);
}
}