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 | |
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')
-rw-r--r-- | sound/pci/cs4281.c | 24 | ||||
-rw-r--r-- | sound/pci/cs46xx/cs46xx_lib.c | 12 | ||||
-rw-r--r-- | sound/pci/emu10k1/emuproc.c | 43 | ||||
-rw-r--r-- | sound/pci/mixart/mixart.c | 12 |
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 | ||
1160 | static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, | 1154 | static 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 | ||
1178 | static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { | 1166 | static 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 | ||
2678 | static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { | 2672 | static 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 | ||
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, |
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; |