mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
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>
This commit is contained in:
parent
24e4a1211f
commit
d97e1b7823
@ -232,10 +232,15 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
|
||||
return -EFAULT;
|
||||
break;
|
||||
case SNDRV_INFO_CONTENT_DATA:
|
||||
if (entry->c.ops->read)
|
||||
if (pos >= entry->size)
|
||||
return 0;
|
||||
if (entry->c.ops->read) {
|
||||
size = entry->size - pos;
|
||||
size = min(count, size);
|
||||
size = entry->c.ops->read(entry,
|
||||
data->file_private_data,
|
||||
file, buffer, count, pos);
|
||||
file, buffer, size, pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((ssize_t) size > 0)
|
||||
@ -282,10 +287,13 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
|
||||
size = count;
|
||||
break;
|
||||
case SNDRV_INFO_CONTENT_DATA:
|
||||
if (entry->c.ops->write)
|
||||
if (entry->c.ops->write && count > 0) {
|
||||
size_t maxsize = entry->size - pos;
|
||||
count = min(count, maxsize);
|
||||
size = entry->c.ops->write(entry,
|
||||
data->file_private_data,
|
||||
file, buffer, count, pos);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((ssize_t) size > 0)
|
||||
|
@ -55,25 +55,18 @@ static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct snd_opl4 *opl4 = entry->private_data;
|
||||
long size;
|
||||
char* buf;
|
||||
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = entry->size - pos;
|
||||
if (size > 0) {
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
snd_opl4_read_memory(opl4, buf, pos, size);
|
||||
if (copy_to_user(_buf, buf, size)) {
|
||||
vfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
buf = vmalloc(count);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
snd_opl4_read_memory(opl4, buf, pos, count);
|
||||
if (copy_to_user(_buf, buf, count)) {
|
||||
vfree(buf);
|
||||
return size;
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
vfree(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,
|
||||
@ -83,25 +76,18 @@ static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,
|
||||
size_t count, size_t pos)
|
||||
{
|
||||
struct snd_opl4 *opl4 = entry->private_data;
|
||||
long size;
|
||||
char *buf;
|
||||
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = entry->size - pos;
|
||||
if (size > 0) {
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(buf, _buf, size)) {
|
||||
vfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
snd_opl4_write_memory(opl4, buf, pos, size);
|
||||
buf = vmalloc(count);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(buf, _buf, count)) {
|
||||
vfree(buf);
|
||||
return size;
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
snd_opl4_write_memory(opl4, buf, pos, count);
|
||||
vfree(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry,
|
||||
|
@ -36,20 +36,14 @@ static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct gus_proc_private *priv = entry->private_data;
|
||||
struct snd_gus_card *gus = priv->gus;
|
||||
int err;
|
||||
|
||||
size = count;
|
||||
if (pos + size > priv->size)
|
||||
size = (long)priv->size - pos;
|
||||
if (size > 0) {
|
||||
if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0)
|
||||
return err;
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
err = snd_gus_dram_read(gus, buf, pos, count, priv->rom);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return count;
|
||||
}
|
||||
|
||||
static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry,
|
||||
|
@ -1144,17 +1144,11 @@ static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct cs4281 *chip = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + size > CS4281_BA0_SIZE)
|
||||
size = (long)CS4281_BA0_SIZE - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, chip->ba0 + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
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,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct cs4281 *chip = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + size > CS4281_BA1_SIZE)
|
||||
size = (long)CS4281_BA1_SIZE - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, chip->ba1 + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
|
||||
|
@ -2662,17 +2662,11 @@ static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct snd_cs46xx_region *region = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + (size_t)size > region->size)
|
||||
size = region->size - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
|
||||
|
@ -346,10 +346,12 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct snd_emu10k1 *emu = entry->private_data;
|
||||
unsigned int offset;
|
||||
int tram_addr = 0;
|
||||
unsigned int *tmp;
|
||||
long res;
|
||||
unsigned int idx;
|
||||
|
||||
if (!strcmp(entry->name, "fx8010_tram_addr")) {
|
||||
offset = TANKMEMADDRREGBASE;
|
||||
@ -361,30 +363,25 @@ static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
|
||||
} else {
|
||||
offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE;
|
||||
}
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = (long)entry->size - pos;
|
||||
if (size > 0) {
|
||||
unsigned int *tmp;
|
||||
long res;
|
||||
unsigned int idx;
|
||||
if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++)
|
||||
if (tram_addr && emu->audigy) {
|
||||
tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11;
|
||||
tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
|
||||
} else
|
||||
tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
|
||||
if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size))
|
||||
res = -EFAULT;
|
||||
else {
|
||||
res = size;
|
||||
|
||||
tmp = kmalloc(count + 8, GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) {
|
||||
unsigned int val;
|
||||
val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
|
||||
if (tram_addr && emu->audigy) {
|
||||
val >>= 11;
|
||||
val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
|
||||
}
|
||||
kfree(tmp);
|
||||
return res;
|
||||
tmp[idx] = val;
|
||||
}
|
||||
return 0;
|
||||
if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count))
|
||||
res = -EFAULT;
|
||||
else
|
||||
res = count;
|
||||
kfree(tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
|
||||
|
@ -1161,13 +1161,7 @@ static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct mixart_mgr *mgr = entry->private_data;
|
||||
unsigned long maxsize;
|
||||
|
||||
if (pos >= MIXART_BA0_SIZE)
|
||||
return 0;
|
||||
maxsize = MIXART_BA0_SIZE - pos;
|
||||
if (count > maxsize)
|
||||
count = maxsize;
|
||||
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
|
||||
if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
|
||||
return -EFAULT;
|
||||
@ -1183,13 +1177,7 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct mixart_mgr *mgr = entry->private_data;
|
||||
unsigned long maxsize;
|
||||
|
||||
if (pos > MIXART_BA1_SIZE)
|
||||
return 0;
|
||||
maxsize = MIXART_BA1_SIZE - pos;
|
||||
if (count > maxsize)
|
||||
count = maxsize;
|
||||
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
|
||||
if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
|
||||
return -EFAULT;
|
||||
|
Loading…
Reference in New Issue
Block a user