diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-04-13 05:33:54 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-04-13 06:01:14 -0400 |
commit | d97e1b78239c7e7e441088e0b644bd3b076002e6 (patch) | |
tree | b05b5085bea932662ce60061d5b4b93834683327 /sound/pci/emu10k1 | |
parent | 24e4a1211f691fc671de44685430dbad757d8487 (diff) |
ALSA: info - Check file position validity in common layer
Check the validity of the file position in the common info layer before
calling read or write callbacks in assumption that entry->size is set up
properly to indicate the max file size.
Removed the redundant checks from the callbacks as well.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/emu10k1')
-rw-r--r-- | sound/pci/emu10k1/emuproc.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 347b2415db59..bc38dd4d071f 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -346,10 +346,12 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, | |||
346 | struct file *file, char __user *buf, | 346 | struct file *file, char __user *buf, |
347 | size_t count, loff_t pos) | 347 | size_t count, loff_t pos) |
348 | { | 348 | { |
349 | long size; | ||
350 | struct snd_emu10k1 *emu = entry->private_data; | 349 | struct snd_emu10k1 *emu = entry->private_data; |
351 | unsigned int offset; | 350 | unsigned int offset; |
352 | int tram_addr = 0; | 351 | int tram_addr = 0; |
352 | unsigned int *tmp; | ||
353 | long res; | ||
354 | unsigned int idx; | ||
353 | 355 | ||
354 | if (!strcmp(entry->name, "fx8010_tram_addr")) { | 356 | if (!strcmp(entry->name, "fx8010_tram_addr")) { |
355 | offset = TANKMEMADDRREGBASE; | 357 | offset = TANKMEMADDRREGBASE; |
@@ -361,30 +363,25 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry, | |||
361 | } else { | 363 | } else { |
362 | offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; | 364 | offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE; |
363 | } | 365 | } |
364 | size = count; | 366 | |
365 | if (pos + size > entry->size) | 367 | tmp = kmalloc(count + 8, GFP_KERNEL); |
366 | size = (long)entry->size - pos; | 368 | if (!tmp) |
367 | if (size > 0) { | 369 | return -ENOMEM; |
368 | unsigned int *tmp; | 370 | for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) { |
369 | long res; | 371 | unsigned int val; |
370 | unsigned int idx; | 372 | val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); |
371 | if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL) | 373 | if (tram_addr && emu->audigy) { |
372 | return -ENOMEM; | 374 | val >>= 11; |
373 | for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++) | 375 | val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; |
374 | if (tram_addr && emu->audigy) { | ||
375 | tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11; | ||
376 | tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20; | ||
377 | } else | ||
378 | tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0); | ||
379 | if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size)) | ||
380 | res = -EFAULT; | ||
381 | else { | ||
382 | res = size; | ||
383 | } | 376 | } |
384 | kfree(tmp); | 377 | tmp[idx] = val; |
385 | return res; | ||
386 | } | 378 | } |
387 | return 0; | 379 | if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count)) |
380 | res = -EFAULT; | ||
381 | else | ||
382 | res = count; | ||
383 | kfree(tmp); | ||
384 | return res; | ||
388 | } | 385 | } |
389 | 386 | ||
390 | static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, | 387 | static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, |