aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-04-13 05:33:54 -0400
committerTakashi Iwai <tiwai@suse.de>2010-04-13 06:01:14 -0400
commitd97e1b78239c7e7e441088e0b644bd3b076002e6 (patch)
treeb05b5085bea932662ce60061d5b4b93834683327 /sound/pci
parent24e4a1211f691fc671de44685430dbad757d8487 (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')
-rw-r--r--sound/pci/cs4281.c24
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c12
-rw-r--r--sound/pci/emu10k1/emuproc.c43
-rw-r--r--sound/pci/mixart/mixart.c12
4 files changed, 29 insertions, 62 deletions
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index b0bba2e86b12..6772070ed492 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1144,17 +1144,11 @@ static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry,
1144 struct file *file, char __user *buf, 1144 struct file *file, char __user *buf,
1145 size_t count, loff_t pos) 1145 size_t count, loff_t pos)
1146{ 1146{
1147 long size;
1148 struct cs4281 *chip = entry->private_data; 1147 struct cs4281 *chip = entry->private_data;
1149 1148
1150 size = count; 1149 if (copy_to_user_fromio(buf, chip->ba0 + pos, count))
1151 if (pos + size > CS4281_BA0_SIZE) 1150 return -EFAULT;
1152 size = (long)CS4281_BA0_SIZE - pos; 1151 return count;
1153 if (size > 0) {
1154 if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
1155 return -EFAULT;
1156 }
1157 return size;
1158} 1152}
1159 1153
1160static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, 1154static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry,
@@ -1162,17 +1156,11 @@ static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry,
1162 struct file *file, char __user *buf, 1156 struct file *file, char __user *buf,
1163 size_t count, loff_t pos) 1157 size_t count, loff_t pos)
1164{ 1158{
1165 long size;
1166 struct cs4281 *chip = entry->private_data; 1159 struct cs4281 *chip = entry->private_data;
1167 1160
1168 size = count; 1161 if (copy_to_user_fromio(buf, chip->ba1 + pos, count))
1169 if (pos + size > CS4281_BA1_SIZE) 1162 return -EFAULT;
1170 size = (long)CS4281_BA1_SIZE - pos; 1163 return count;
1171 if (size > 0) {
1172 if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
1173 return -EFAULT;
1174 }
1175 return size;
1176} 1164}
1177 1165
1178static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { 1166static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 08117b142381..aad37082cb6e 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2662,17 +2662,11 @@ static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
2662 struct file *file, char __user *buf, 2662 struct file *file, char __user *buf,
2663 size_t count, loff_t pos) 2663 size_t count, loff_t pos)
2664{ 2664{
2665 long size;
2666 struct snd_cs46xx_region *region = entry->private_data; 2665 struct snd_cs46xx_region *region = entry->private_data;
2667 2666
2668 size = count; 2667 if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
2669 if (pos + (size_t)size > region->size) 2668 return -EFAULT;
2670 size = region->size - pos; 2669 return count;
2671 if (size > 0) {
2672 if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
2673 return -EFAULT;
2674 }
2675 return size;
2676} 2670}
2677 2671
2678static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { 2672static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
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
390static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry, 387static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index b5df78bcc25b..be95e005c81d 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1161,13 +1161,7 @@ static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
1161 size_t count, loff_t pos) 1161 size_t count, loff_t pos)
1162{ 1162{
1163 struct mixart_mgr *mgr = entry->private_data; 1163 struct mixart_mgr *mgr = entry->private_data;
1164 unsigned long maxsize;
1165 1164
1166 if (pos >= MIXART_BA0_SIZE)
1167 return 0;
1168 maxsize = MIXART_BA0_SIZE - pos;
1169 if (count > maxsize)
1170 count = maxsize;
1171 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ 1165 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1172 if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count)) 1166 if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
1173 return -EFAULT; 1167 return -EFAULT;
@@ -1183,13 +1177,7 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
1183 size_t count, loff_t pos) 1177 size_t count, loff_t pos)
1184{ 1178{
1185 struct mixart_mgr *mgr = entry->private_data; 1179 struct mixart_mgr *mgr = entry->private_data;
1186 unsigned long maxsize;
1187 1180
1188 if (pos > MIXART_BA1_SIZE)
1189 return 0;
1190 maxsize = MIXART_BA1_SIZE - pos;
1191 if (count > maxsize)
1192 count = maxsize;
1193 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */ 1181 count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
1194 if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count)) 1182 if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
1195 return -EFAULT; 1183 return -EFAULT;