Jiri Slaby 0b14a5
From: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 0b14a5
Date: Mon, 19 Oct 2020 10:55:16 +0200
Jiri Slaby 0b14a5
Subject: vt: keyboard, simplify vt_kdgkbsent
Jiri Slaby 0b14a5
Git-commit: 6ca03f90527e499dd5e32d6522909e2ad390896b
Jiri Slaby 0b14a5
Patch-mainline: 5.10-rc2
Jiri Slaby 0b14a5
References: bnc#1177766 CVE-2020-25656
Jiri Slaby 0b14a5
Jiri Slaby 0b14a5
Use 'strlen' of the string, add one for NUL terminator and simply do
Jiri Slaby 0b14a5
'copy_to_user' instead of the explicit 'for' loop. This makes the
Jiri Slaby 0b14a5
KDGKBSENT case more compact.
Jiri Slaby 0b14a5
Jiri Slaby 0b14a5
The only thing we need to take care about is NULL 'func_table[i]'. Use
Jiri Slaby 0b14a5
an empty string in that case.
Jiri Slaby 0b14a5
Jiri Slaby 0b14a5
The original check for overflow could never trigger as the func_buf
Jiri Slaby 0b14a5
strings are always shorter or equal to 'struct kbsentry's.
Jiri Slaby 0b14a5
Jiri Slaby 0b14a5
Cc: <stable@vger.kernel.org>
Jiri Slaby 0b14a5
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 0b14a5
Link: https://lore.kernel.org/r/20201019085517.10176-1-jslaby@suse.cz
Jiri Slaby 0b14a5
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 0b14a5
---
Jiri Slaby 0b14a5
 drivers/tty/vt/keyboard.c |   28 +++++++++-------------------
Jiri Slaby 0b14a5
 1 file changed, 9 insertions(+), 19 deletions(-)
Jiri Slaby 0b14a5
Jiri Slaby 0b14a5
--- a/drivers/tty/vt/keyboard.c
Jiri Slaby 0b14a5
+++ b/drivers/tty/vt/keyboard.c
Jiri Slaby 0b14a5
@@ -1964,9 +1964,7 @@ out:
Jiri Slaby 0b14a5
 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
Jiri Slaby 0b14a5
 {
Jiri Slaby 0b14a5
 	struct kbsentry *kbs;
Jiri Slaby 0b14a5
-	char *p;
Jiri Slaby 0b14a5
 	u_char *q;
Jiri Slaby 0b14a5
-	u_char __user *up;
Jiri Slaby 0b14a5
 	int sz, fnw_sz;
Jiri Slaby 0b14a5
 	int delta;
Jiri Slaby 0b14a5
 	char *first_free, *fj, *fnw;
Jiri Slaby 0b14a5
@@ -1992,23 +1990,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
Jiri Slaby 0b14a5
 	i = kbs->kb_func;
Jiri Slaby 0b14a5
 
Jiri Slaby 0b14a5
 	switch (cmd) {
Jiri Slaby 0b14a5
-	case KDGKBSENT:
Jiri Slaby 0b14a5
-		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
Jiri Slaby 0b14a5
-						  a struct member */
Jiri Slaby 0b14a5
-		up = user_kdgkb->kb_string;
Jiri Slaby 0b14a5
-		p = func_table[i];
Jiri Slaby 0b14a5
-		if(p)
Jiri Slaby 0b14a5
-			for ( ; *p && sz; p++, sz--)
Jiri Slaby 0b14a5
-				if (put_user(*p, up++)) {
Jiri Slaby 0b14a5
-					ret = -EFAULT;
Jiri Slaby 0b14a5
-					goto reterr;
Jiri Slaby 0b14a5
-				}
Jiri Slaby 0b14a5
-		if (put_user('\0', up)) {
Jiri Slaby 0b14a5
-			ret = -EFAULT;
Jiri Slaby 0b14a5
-			goto reterr;
Jiri Slaby 0b14a5
-		}
Jiri Slaby 0b14a5
-		kfree(kbs);
Jiri Slaby 0b14a5
-		return ((p && *p) ? -EOVERFLOW : 0);
Jiri Slaby 0b14a5
+	case KDGKBSENT: {
Jiri Slaby 0b14a5
+		/* size should have been a struct member */
Jiri Slaby 0b14a5
+		unsigned char *from = func_table[i] ? : "";
Jiri Slaby 0b14a5
+
Jiri Slaby 0b14a5
+		ret = copy_to_user(user_kdgkb->kb_string, from,
Jiri Slaby 0b14a5
+				strlen(from) + 1) ? -EFAULT : 0;
Jiri Slaby 0b14a5
+
Jiri Slaby 0b14a5
+		goto reterr;
Jiri Slaby 0b14a5
+	}
Jiri Slaby 0b14a5
 	case KDSKBSENT:
Jiri Slaby 0b14a5
 		if (!perm) {
Jiri Slaby 0b14a5
 			ret = -EPERM;