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: Jiri Slaby <jslaby@suse.cz> Link: https://lore.kernel.org/r/20200818085706.12163-5-jslaby@suse.cz Signed-off-by: Greg 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: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e9399d4ea5
commit
74e644795d
@@ -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))
|
||||
|
||||
size = 2 * size + HEADER_SIZE;
|
||||
} 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;
|
||||
|
||||
Reference in New Issue
Block a user