Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d97e1b78 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 24e4a121
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -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)
+16 −30
Original line number Diff line number Diff line
@@ -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);
	buf = vmalloc(count);
	if (!buf)
		return -ENOMEM;
		snd_opl4_read_memory(opl4, buf, pos, size);
		if (copy_to_user(_buf, buf, size)) {
	snd_opl4_read_memory(opl4, buf, pos, count);
	if (copy_to_user(_buf, buf, count)) {
		vfree(buf);
		return -EFAULT;
	}
	vfree(buf);
		return size;
	}
	return 0;
	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);
	buf = vmalloc(count);
	if (!buf)
		return -ENOMEM;
		if (copy_from_user(buf, _buf, size)) {
	if (copy_from_user(buf, _buf, count)) {
		vfree(buf);
		return -EFAULT;
	}
		snd_opl4_write_memory(opl4, buf, pos, size);
	snd_opl4_write_memory(opl4, buf, pos, count);
	vfree(buf);
		return size;
	}
	return 0;
	return count;
}

static loff_t snd_opl4_mem_proc_llseek(struct snd_info_entry *entry,
+4 −10
Original line number Diff line number Diff line
@@ -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)
	err = snd_gus_dram_read(gus, buf, pos, count, priv->rom);
	if (err < 0)
		return err;
		return size;
	}
	return 0;
	return count;
}			

static loff_t snd_gf1_mem_proc_llseek(struct snd_info_entry *entry,
+6 −18
Original line number Diff line number Diff line
@@ -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))
	if (copy_to_user_fromio(buf, chip->ba0 + pos, count))
		return -EFAULT;
	}
	return size;
	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))
	if (copy_to_user_fromio(buf, chip->ba1 + pos, count))
		return -EFAULT;
	}
	return size;
	return count;
}

static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
+3 −9
Original line number Diff line number Diff line
@@ -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))
	if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
		return -EFAULT;
	}
	return size;
	return count;
}

static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
Loading