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

Commit 7e5b58bc authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman
Browse files

printk: /dev/kmsg - properly support writev() to avoid interleaved printk() lines



printk: /dev/kmsg - properly support writev() to avoid interleaved printk lines

We should avoid calling printk() in a loop, when we pass a single
string to /dev/kmsg with writev().

Cc: Lennart Poettering <lennart@poettering.net>
Signed-off-by: default avatarKay Sievers <kay.sievers@vrfy.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 47296b19
Loading
Loading
Loading
Loading
+26 −15
Original line number Diff line number Diff line
@@ -806,29 +806,40 @@ static const struct file_operations oldmem_fops = {
};
#endif

static ssize_t kmsg_write(struct file *file, const char __user *buf,
			  size_t count, loff_t *ppos)
static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
			   unsigned long count, loff_t pos)
{
	char *tmp;
	ssize_t ret;
	char *line, *p;
	int len, i;
	ssize_t ret = -EFAULT;

	tmp = kmalloc(count + 1, GFP_KERNEL);
	if (tmp == NULL)
	len = iov_length(iv, count);
	line = p = kmalloc(len + 1, GFP_KERNEL);
	if (line == NULL)
		return -ENOMEM;
	ret = -EFAULT;
	if (!copy_from_user(tmp, buf, count)) {
		tmp[count] = 0;
		ret = printk("%s", tmp);
		if (ret > count)
			/* printk can add a prefix */
			ret = count;

	/*
	 * copy all vectors into a single string, to ensure we do
	 * not interleave our log line with other printk calls
	 */
	for (i = 0; i < count; i++) {
		if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len))
			goto out;
		p += iv[i].iov_len;
	}
	kfree(tmp);
	p[0] = '\0';

	ret = printk("%s", line);
	/* printk can add a prefix */
	if (ret > len)
		ret = len;
out:
	kfree(line);
	return ret;
}

static const struct file_operations kmsg_fops = {
	.write = kmsg_write,
	.aio_write = kmsg_writev,
	.llseek = noop_llseek,
};