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

Commit 74e64479 authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

vc_screen: rewrite vcs_size to accept vc, not inode



[ Upstream commit 71d4abfab322e827a75304431fe0fad3c805cb80 ]

It is weird to fetch the information from the inode over and over. Read
and write already have the needed information, so rewrite vcs_size to
accept a vc, attr and unicode and adapt vcs_lseek to that.

Also make sure all sites check the return value of vcs_size for errors.

And document it using kernel-doc.

Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20200818085706.12163-5-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 8fb9ea65c9d1 ("vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent e9399d4e
Loading
Loading
Loading
Loading
+29 −17
Original line number Diff line number Diff line
@@ -200,39 +200,47 @@ vcs_vc(struct inode *inode, int *viewed)
	return vc_cons[currcons].d;
}

/*
 * Returns size for VC carried by inode.
/**
 * vcs_size -- return size for a VC in @vc
 * @vc: which VC
 * @attr: does it use attributes?
 * @unicode: is it unicode?
 *
 * Must be called with console_lock.
 */
static int
vcs_size(struct inode *inode)
static int vcs_size(const struct vc_data *vc, bool attr, bool unicode)
{
	int size;
	struct vc_data *vc;

	WARN_CONSOLE_UNLOCKED();

	vc = vcs_vc(inode, NULL);
	if (!vc)
		return -ENXIO;

	size = vc->vc_rows * vc->vc_cols;

	if (use_attributes(inode)) {
		if (use_unicode(inode))
	if (attr) {
		if (unicode)
			return -EOPNOTSUPP;

		size = 2 * size + HEADER_SIZE;
	} else if (use_unicode(inode))
	} else if (unicode)
		size *= 4;

	return size;
}

static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
{
	struct inode *inode = file_inode(file);
	struct vc_data *vc;
	int size;

	console_lock();
	size = vcs_size(file_inode(file));
	vc = vcs_vc(inode, NULL);
	if (!vc) {
		console_unlock();
		return -ENXIO;
	}

	size = vcs_size(vc, use_attributes(inode), use_unicode(inode));
	console_unlock();
	if (size < 0)
		return size;
@@ -294,7 +302,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
		 * as copy_to_user at the end of this loop
		 * could sleep.
		 */
		size = vcs_size(inode);
		size = vcs_size(vc, attr, uni_mode);
		if (size < 0) {
			ret = size;
			break;
@@ -476,7 +484,11 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
	if (!vc)
		goto unlock_out;

	size = vcs_size(inode);
	size = vcs_size(vc, attr, false);
	if (size < 0) {
		ret = size;
		goto unlock_out;
	}
	ret = -EINVAL;
	if (pos < 0 || pos > size)
		goto unlock_out;
@@ -515,7 +527,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
		 * the user buffer, so recheck.
		 * Return data written up to now on failure.
		 */
		size = vcs_size(inode);
		size = vcs_size(vc, attr, false);
		if (size < 0) {
			if (written)
				break;