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

Commit d3e74f2e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drivers: soc: ramdump: Ensure aligned addresses are passed to copy_to_user"

parents 4b61ab9e 7991893d
Loading
Loading
Loading
Loading
+40 −8
Original line number Diff line number Diff line
@@ -99,10 +99,11 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
{
	struct ramdump_device *rd_dev = container_of(filep->private_data,
				struct ramdump_device, device);
	void *device_mem = NULL;
	unsigned long data_left = 0;
	void *device_mem = NULL, *origdevice_mem = NULL;
	unsigned long data_left = 0, bytes_before, bytes_after;
	unsigned long addr = 0;
	size_t copy_size = 0;
	size_t copy_size = 0, alignsize;
	unsigned char *alignbuf = NULL, *finalbuf = NULL;
	int ret = 0;
	loff_t orig_pos = *pos;

@@ -143,6 +144,7 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
	copy_size = min(count, (size_t)MAX_IOREMAP_SIZE);
	copy_size = min((unsigned long)copy_size, data_left);
	device_mem = ioremap_nocache(addr, copy_size);
	origdevice_mem = device_mem;

	if (device_mem == NULL) {
		pr_err("Ramdump(%s): Unable to ioremap: addr %lx, size %zd\n",
@@ -152,16 +154,44 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
		goto ramdump_done;
	}

	if (copy_to_user(buf, device_mem, copy_size)) {
		pr_err("Ramdump(%s): Couldn't copy all data to user.",
	alignbuf = kzalloc(copy_size, GFP_KERNEL);
	if (!alignbuf) {
		pr_err("Ramdump(%s): Unable to alloc mem for aligned buf\n",
				rd_dev->name);
		iounmap(device_mem);
		rd_dev->ramdump_status = -1;
		ret = -ENOMEM;
		goto ramdump_done;
	}

	finalbuf = alignbuf;
	alignsize = copy_size;

	if ((unsigned long)device_mem & 0x7) {
		bytes_before = 8 - ((unsigned long)device_mem & 0x7);
		memcpy_fromio(alignbuf, device_mem, bytes_before);
		device_mem += bytes_before;
		alignbuf += bytes_before;
		alignsize -= bytes_before;
	}

	if (alignsize & 0x7) {
		bytes_after = alignsize & 0x7;
		memcpy(alignbuf, device_mem, alignsize - bytes_after);
		device_mem += alignsize - bytes_after;
		alignbuf += (alignsize - bytes_after);
		alignsize = bytes_after;
		memcpy_fromio(alignbuf, device_mem, alignsize);
	} else
		memcpy(alignbuf, device_mem, alignsize);

	if (copy_to_user(buf, finalbuf, copy_size)) {
		rd_dev->ramdump_status = -1;
		ret = -EFAULT;
		goto ramdump_done;
	}

	iounmap(device_mem);
	iounmap(origdevice_mem);
	kfree(finalbuf);
	*pos += copy_size;

	pr_debug("Ramdump(%s): Read %zd bytes from address %lx.",
@@ -170,6 +200,8 @@ static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
	return *pos - orig_pos;

ramdump_done:
	iounmap(origdevice_mem);
	kfree(finalbuf);
	rd_dev->data_ready = 0;
	*pos = 0;
	complete(&rd_dev->ramdump_complete);