All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl
@ 2020-10-16 12:24 Jiri Slaby
  2020-10-16 12:24 ` [PATCH 2/3] vt: keyboard, simplify vt_kdgkbsent Jiri Slaby
  2020-10-16 12:24 ` [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers Jiri Slaby
  0 siblings, 2 replies; 6+ messages in thread
From: Jiri Slaby @ 2020-10-16 12:24 UTC (permalink / raw)
  To: gregkh; +Cc: linux-serial, linux-kernel, Minh Yuan, Jiri Slaby

KDGKBSENT (the getter) needs only user_kdgkb->kb_func from the
userspace, i.e. the index. So do the complete copy only in KDSKBSENT
(the setter). That means, we obtain the index before the switch-case
and use it in both paths and copy the string only in the setter case.
And we do it by strndup_user helper now which was not available when
this function was written.

Given we copy the two members of struct kbsentry separately, we no
longer need a local definition. Hence we need to change all the sizeofs
here too.

And also the getter now returns in all fail paths, not freeing the
setter's string.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/tty/vt/keyboard.c | 51 ++++++++++++++++-----------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 0db53b5b3acf..d8e2452da1bd 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1994,7 +1994,7 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
 /* FIXME: This one needs untangling and locking */
 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 {
-	struct kbsentry *kbs;
+	char *kbs;
 	char *p;
 	u_char *q;
 	u_char __user *up;
@@ -2008,43 +2008,34 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 	if (!capable(CAP_SYS_TTY_CONFIG))
 		perm = 0;
 
-	kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
-	if (!kbs) {
-		ret = -ENOMEM;
-		goto reterr;
-	}
+	if (get_user(i, &user_kdgkb->kb_func))
+		return -EFAULT;
 
-	/* we mostly copy too much here (512bytes), but who cares ;) */
-	if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
-		ret = -EFAULT;
-		goto reterr;
-	}
-	kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
-	i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
+	i = array_index_nospec(i, MAX_NR_FUNC);
 
 	switch (cmd) {
 	case KDGKBSENT:
-		sz = sizeof(kbs->kb_string) - 1; /* sz should have been
-						  a struct member */
+		/* sz should have been a struct member */
+		sz = sizeof_field(struct kbsentry, kb_string) - 1;
 		up = user_kdgkb->kb_string;
 		p = func_table[i];
 		if(p)
 			for ( ; *p && sz; p++, sz--)
-				if (put_user(*p, up++)) {
-					ret = -EFAULT;
-					goto reterr;
-				}
-		if (put_user('\0', up)) {
-			ret = -EFAULT;
-			goto reterr;
-		}
-		kfree(kbs);
+				if (put_user(*p, up++))
+					return -EFAULT;
+
+		if (put_user('\0', up))
+			return -EFAULT;
+
 		return ((p && *p) ? -EOVERFLOW : 0);
 	case KDSKBSENT:
-		if (!perm) {
-			ret = -EPERM;
-			goto reterr;
-		}
+		if (!perm)
+			return -EPERM;
+
+		kbs = strndup_user(user_kdgkb->kb_string,
+				sizeof(user_kdgkb->kb_string));
+		if (IS_ERR(kbs))
+			return PTR_ERR(kbs);
 
 		fnw = NULL;
 		fnw_sz = 0;
@@ -2062,7 +2053,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 		else
 			fj = first_free;
 		/* buffer usage increase by new entry */
-		delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
+		delta = (q ? -strlen(q) : 1) + strlen(kbs);
 
 		if (delta <= funcbufleft) { 	/* it fits in current buf */
 		    if (j < MAX_NR_FUNC) {
@@ -2114,7 +2105,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 		    funcbufsize = sz;
 		}
 		/* finally insert item itself */
-		strcpy(func_table[i], kbs->kb_string);
+		strcpy(func_table[i], kbs);
 		spin_unlock_irqrestore(&func_buf_lock, flags);
 		break;
 	}
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] vt: keyboard, simplify vt_kdgkbsent
  2020-10-16 12:24 [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl Jiri Slaby
@ 2020-10-16 12:24 ` Jiri Slaby
  2020-10-16 12:24 ` [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers Jiri Slaby
  1 sibling, 0 replies; 6+ messages in thread
From: Jiri Slaby @ 2020-10-16 12:24 UTC (permalink / raw)
  To: gregkh; +Cc: linux-serial, linux-kernel, Minh Yuan, Jiri Slaby

Use 'strlen' of the string, add one for NUL and simply do 'copy_to_user'
instead of the explicit 'for' loop. This makes the KDGKBSENT case more
compact.

The only thing we need to take care about is NULL 'from'.

The original check for overflow could never trigger as the func_buf
(called 'from' here) strings are always shorter or equal to struct
kbsentry's.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/tty/vt/keyboard.c | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index d8e2452da1bd..68f9f6a62d02 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1995,9 +1995,7 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 {
 	char *kbs;
-	char *p;
 	u_char *q;
-	u_char __user *up;
 	int sz, fnw_sz;
 	int delta;
 	char *first_free, *fj, *fnw;
@@ -2014,20 +2012,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 	i = array_index_nospec(i, MAX_NR_FUNC);
 
 	switch (cmd) {
-	case KDGKBSENT:
-		/* sz should have been a struct member */
-		sz = sizeof_field(struct kbsentry, kb_string) - 1;
-		up = user_kdgkb->kb_string;
-		p = func_table[i];
-		if(p)
-			for ( ; *p && sz; p++, sz--)
-				if (put_user(*p, up++))
-					return -EFAULT;
-
-		if (put_user('\0', up))
+	case KDGKBSENT: {
+		/* size should have been a struct member */
+		unsigned char *from = func_table[i] ? : "";
+
+		if (copy_to_user(user_kdgkb->kb_string, from, strlen(from) + 1))
 			return -EFAULT;
 
-		return ((p && *p) ? -EOVERFLOW : 0);
+		return 0;
+	}
 	case KDSKBSENT:
 		if (!perm)
 			return -EPERM;
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers
  2020-10-16 12:24 [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl Jiri Slaby
  2020-10-16 12:24 ` [PATCH 2/3] vt: keyboard, simplify vt_kdgkbsent Jiri Slaby
@ 2020-10-16 12:24 ` Jiri Slaby
  2020-10-16 13:20   ` Greg KH
  1 sibling, 1 reply; 6+ messages in thread
From: Jiri Slaby @ 2020-10-16 12:24 UTC (permalink / raw)
  To: gregkh; +Cc: linux-serial, linux-kernel, Minh Yuan, Jiri Slaby

Both read-side users of func_table/func_buf need locking. Without that,
one can easily confuse the code by repeatedly setting altering strings
like:
while (1)
	for (a = 0; a < 2; a++) {
		struct kbsentry kbs = {};
		strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
		ioctl(fd, KDSKBSENT, &kbs);
	}

When that program runs, one can get unexpected output by holding F1
(note the unxpected period on the last line):
.
88888
.8888

So protect all accesses to 'func_table' (and func_buf) by preexisting
'func_buf_lock'.

It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep.
On the other hand, KDGKBSENT needs a local (atomic) copy of the string
because copy_to_user can sleep.

Likely fixes CVE-2020-25656.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
---
 drivers/tty/vt/keyboard.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 68f9f6a62d02..68b1acc0074c 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag)
 		return;
 
 	if ((unsigned)value < ARRAY_SIZE(func_table)) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&func_buf_lock, flags);
 		if (func_table[value])
 			puts_queue(vc, func_table[value]);
+		spin_unlock_irqrestore(&func_buf_lock, flags);
+
 	} else
 		pr_err("k_fn called with value=%d\n", value);
 }
@@ -1991,7 +1996,7 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
 #undef s
 #undef v
 
-/* FIXME: This one needs untangling and locking */
+/* FIXME: This one needs untangling */
 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 {
 	char *kbs;
@@ -2014,12 +2019,23 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 	switch (cmd) {
 	case KDGKBSENT: {
 		/* size should have been a struct member */
-		unsigned char *from = func_table[i] ? : "";
+		char *func_copy;
+		ssize_t len = sizeof(user_kdgkb->kb_string);
 
-		if (copy_to_user(user_kdgkb->kb_string, from, strlen(from) + 1))
-			return -EFAULT;
+		func_copy = kmalloc(len, GFP_KERNEL);
+		if (!func_copy)
+			return -ENOMEM;
 
-		return 0;
+		spin_lock_irqsave(&func_buf_lock, flags);
+		len = strlcpy(func_copy, func_table[i] ? : "", len);
+		spin_unlock_irqrestore(&func_buf_lock, flags);
+
+		ret = copy_to_user(user_kdgkb->kb_string, func_copy, len + 1) ?
+			-EFAULT : 0;
+
+		kfree(func_copy);
+
+		return ret;
 	}
 	case KDSKBSENT:
 		if (!perm)
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers
  2020-10-16 12:24 ` [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers Jiri Slaby
@ 2020-10-16 13:20   ` Greg KH
  2020-10-19  8:00     ` Jiri Slaby
  0 siblings, 1 reply; 6+ messages in thread
From: Greg KH @ 2020-10-16 13:20 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-serial, linux-kernel, Minh Yuan

On Fri, Oct 16, 2020 at 02:24:12PM +0200, Jiri Slaby wrote:
> Both read-side users of func_table/func_buf need locking. Without that,
> one can easily confuse the code by repeatedly setting altering strings
> like:
> while (1)
> 	for (a = 0; a < 2; a++) {
> 		struct kbsentry kbs = {};
> 		strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
> 		ioctl(fd, KDSKBSENT, &kbs);
> 	}
> 
> When that program runs, one can get unexpected output by holding F1
> (note the unxpected period on the last line):
> .
> 88888
> .8888
> 
> So protect all accesses to 'func_table' (and func_buf) by preexisting
> 'func_buf_lock'.
> 
> It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep.
> On the other hand, KDGKBSENT needs a local (atomic) copy of the string
> because copy_to_user can sleep.
> 
> Likely fixes CVE-2020-25656.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
> ---
>  drivers/tty/vt/keyboard.c | 26 +++++++++++++++++++++-----
>  1 file changed, 21 insertions(+), 5 deletions(-)

So all 3 of these should go to 5.10-final?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers
  2020-10-16 13:20   ` Greg KH
@ 2020-10-19  8:00     ` Jiri Slaby
  0 siblings, 0 replies; 6+ messages in thread
From: Jiri Slaby @ 2020-10-19  8:00 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-serial, linux-kernel, Minh Yuan

On 16. 10. 20, 15:20, Greg KH wrote:
> On Fri, Oct 16, 2020 at 02:24:12PM +0200, Jiri Slaby wrote:
>> Both read-side users of func_table/func_buf need locking. Without that,
>> one can easily confuse the code by repeatedly setting altering strings
>> like:
>> while (1)
>> 	for (a = 0; a < 2; a++) {
>> 		struct kbsentry kbs = {};
>> 		strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
>> 		ioctl(fd, KDSKBSENT, &kbs);
>> 	}
>>
>> When that program runs, one can get unexpected output by holding F1
>> (note the unxpected period on the last line):
>> .
>> 88888
>> .8888
>>
>> So protect all accesses to 'func_table' (and func_buf) by preexisting
>> 'func_buf_lock'.
>>
>> It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep.
>> On the other hand, KDGKBSENT needs a local (atomic) copy of the string
>> because copy_to_user can sleep.
>>
>> Likely fixes CVE-2020-25656.
>>
>> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
>> Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
>> ---
>>   drivers/tty/vt/keyboard.c | 26 +++++++++++++++++++++-----
>>   1 file changed, 21 insertions(+), 5 deletions(-)
> 
> So all 3 of these should go to 5.10-final?

Let me try to eliminate also patch 1/3 which I now think is possible.

-- 
js
suse labs

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl
@ 2020-10-16 14:13 kernel test robot
  0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2020-10-16 14:13 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 11804 bytes --]

CC: kbuild-all(a)lists.01.org
In-Reply-To: <20201016122412.31767-1-jslaby@suse.cz>
References: <20201016122412.31767-1-jslaby@suse.cz>
TO: Jiri Slaby <jslaby@suse.cz>

Hi Jiri,

I love your patch! Perhaps something to improve:

[auto build test WARNING on tty/tty-testing]
[also build test WARNING on v5.9 next-20201016]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jiri-Slaby/vt-keyboard-reorder-user-buffer-handling-in-vt_do_kdgkb_ioctl/20201016-202459
base:   https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
:::::: branch date: 2 hours ago
:::::: commit date: 2 hours ago
config: i386-randconfig-m021-20201016 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
drivers/tty/vt/keyboard.c:2114 vt_do_kdgkb_ioctl() error: uninitialized symbol 'kbs'.

Old smatch warnings:
drivers/tty/vt/keyboard.c:1909 vt_do_kdsk_ioctl() warn: potential spectre issue 'key_map' [r]
drivers/tty/vt/keyboard.c:2052 vt_do_kdgkb_ioctl() warn: potential spectre issue 'func_table' [r] (local cap)
drivers/tty/vt/keyboard.c:2061 vt_do_kdgkb_ioctl() warn: possible spectre second half.  'fj'
drivers/tty/vt/keyboard.c:2067 vt_do_kdgkb_ioctl() warn: possible spectre second half.  'fj'
drivers/tty/vt/keyboard.c:2086 vt_do_kdgkb_ioctl() warn: possible spectre second half.  'fj'
drivers/tty/vt/keyboard.c:2088 vt_do_kdgkb_ioctl() warn: possible spectre second half.  'fj'

vim +/kbs +2114 drivers/tty/vt/keyboard.c

079c9534a96da9a Alan Cox           2012-02-28  1993  
079c9534a96da9a Alan Cox           2012-02-28  1994  /* FIXME: This one needs untangling and locking */
079c9534a96da9a Alan Cox           2012-02-28  1995  int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
079c9534a96da9a Alan Cox           2012-02-28  1996  {
987bbe4f15e721c Jiri Slaby         2020-10-16  1997  	char *kbs;
079c9534a96da9a Alan Cox           2012-02-28  1998  	char *p;
079c9534a96da9a Alan Cox           2012-02-28  1999  	u_char *q;
079c9534a96da9a Alan Cox           2012-02-28  2000  	u_char __user *up;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2001  	int sz, fnw_sz;
079c9534a96da9a Alan Cox           2012-02-28  2002  	int delta;
079c9534a96da9a Alan Cox           2012-02-28  2003  	char *first_free, *fj, *fnw;
079c9534a96da9a Alan Cox           2012-02-28  2004  	int i, j, k;
079c9534a96da9a Alan Cox           2012-02-28  2005  	int ret;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2006  	unsigned long flags;
079c9534a96da9a Alan Cox           2012-02-28  2007  
079c9534a96da9a Alan Cox           2012-02-28  2008  	if (!capable(CAP_SYS_TTY_CONFIG))
079c9534a96da9a Alan Cox           2012-02-28  2009  		perm = 0;
079c9534a96da9a Alan Cox           2012-02-28  2010  
987bbe4f15e721c Jiri Slaby         2020-10-16  2011  	if (get_user(i, &user_kdgkb->kb_func))
987bbe4f15e721c Jiri Slaby         2020-10-16  2012  		return -EFAULT;
079c9534a96da9a Alan Cox           2012-02-28  2013  
987bbe4f15e721c Jiri Slaby         2020-10-16  2014  	i = array_index_nospec(i, MAX_NR_FUNC);
079c9534a96da9a Alan Cox           2012-02-28  2015  
079c9534a96da9a Alan Cox           2012-02-28  2016  	switch (cmd) {
079c9534a96da9a Alan Cox           2012-02-28  2017  	case KDGKBSENT:
987bbe4f15e721c Jiri Slaby         2020-10-16  2018  		/* sz should have been a struct member */
987bbe4f15e721c Jiri Slaby         2020-10-16  2019  		sz = sizeof_field(struct kbsentry, kb_string) - 1;
079c9534a96da9a Alan Cox           2012-02-28  2020  		up = user_kdgkb->kb_string;
079c9534a96da9a Alan Cox           2012-02-28  2021  		p = func_table[i];
079c9534a96da9a Alan Cox           2012-02-28  2022  		if(p)
079c9534a96da9a Alan Cox           2012-02-28  2023  			for ( ; *p && sz; p++, sz--)
987bbe4f15e721c Jiri Slaby         2020-10-16  2024  				if (put_user(*p, up++))
987bbe4f15e721c Jiri Slaby         2020-10-16  2025  					return -EFAULT;
987bbe4f15e721c Jiri Slaby         2020-10-16  2026  
987bbe4f15e721c Jiri Slaby         2020-10-16  2027  		if (put_user('\0', up))
987bbe4f15e721c Jiri Slaby         2020-10-16  2028  			return -EFAULT;
987bbe4f15e721c Jiri Slaby         2020-10-16  2029  
079c9534a96da9a Alan Cox           2012-02-28  2030  		return ((p && *p) ? -EOVERFLOW : 0);
079c9534a96da9a Alan Cox           2012-02-28  2031  	case KDSKBSENT:
987bbe4f15e721c Jiri Slaby         2020-10-16  2032  		if (!perm)
987bbe4f15e721c Jiri Slaby         2020-10-16  2033  			return -EPERM;
987bbe4f15e721c Jiri Slaby         2020-10-16  2034  
987bbe4f15e721c Jiri Slaby         2020-10-16  2035  		kbs = strndup_user(user_kdgkb->kb_string,
987bbe4f15e721c Jiri Slaby         2020-10-16  2036  				sizeof(user_kdgkb->kb_string));
987bbe4f15e721c Jiri Slaby         2020-10-16  2037  		if (IS_ERR(kbs))
987bbe4f15e721c Jiri Slaby         2020-10-16  2038  			return PTR_ERR(kbs);
079c9534a96da9a Alan Cox           2012-02-28  2039  
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2040  		fnw = NULL;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2041  		fnw_sz = 0;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2042  		/* race aginst other writers */
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2043  		again:
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2044  		spin_lock_irqsave(&func_buf_lock, flags);
079c9534a96da9a Alan Cox           2012-02-28  2045  		q = func_table[i];
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2046  
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2047  		/* fj pointer to next entry after 'q' */
079c9534a96da9a Alan Cox           2012-02-28  2048  		first_free = funcbufptr + (funcbufsize - funcbufleft);
079c9534a96da9a Alan Cox           2012-02-28  2049  		for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
079c9534a96da9a Alan Cox           2012-02-28  2050  			;
079c9534a96da9a Alan Cox           2012-02-28  2051  		if (j < MAX_NR_FUNC)
079c9534a96da9a Alan Cox           2012-02-28  2052  			fj = func_table[j];
079c9534a96da9a Alan Cox           2012-02-28  2053  		else
079c9534a96da9a Alan Cox           2012-02-28  2054  			fj = first_free;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2055  		/* buffer usage increase by new entry */
987bbe4f15e721c Jiri Slaby         2020-10-16  2056  		delta = (q ? -strlen(q) : 1) + strlen(kbs);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2057  
079c9534a96da9a Alan Cox           2012-02-28  2058  		if (delta <= funcbufleft) { 	/* it fits in current buf */
079c9534a96da9a Alan Cox           2012-02-28  2059  		    if (j < MAX_NR_FUNC) {
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2060  			/* make enough space for new entry@'fj' */
079c9534a96da9a Alan Cox           2012-02-28  2061  			memmove(fj + delta, fj, first_free - fj);
079c9534a96da9a Alan Cox           2012-02-28  2062  			for (k = j; k < MAX_NR_FUNC; k++)
079c9534a96da9a Alan Cox           2012-02-28  2063  			    if (func_table[k])
079c9534a96da9a Alan Cox           2012-02-28  2064  				func_table[k] += delta;
079c9534a96da9a Alan Cox           2012-02-28  2065  		    }
079c9534a96da9a Alan Cox           2012-02-28  2066  		    if (!q)
079c9534a96da9a Alan Cox           2012-02-28  2067  		      func_table[i] = fj;
079c9534a96da9a Alan Cox           2012-02-28  2068  		    funcbufleft -= delta;
079c9534a96da9a Alan Cox           2012-02-28  2069  		} else {			/* allocate a larger buffer */
079c9534a96da9a Alan Cox           2012-02-28  2070  		    sz = 256;
079c9534a96da9a Alan Cox           2012-02-28  2071  		    while (sz < funcbufsize - funcbufleft + delta)
079c9534a96da9a Alan Cox           2012-02-28  2072  		      sz <<= 1;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2073  		    if (fnw_sz != sz) {
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2074  		      spin_unlock_irqrestore(&func_buf_lock, flags);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2075  		      kfree(fnw);
079c9534a96da9a Alan Cox           2012-02-28  2076  		      fnw = kmalloc(sz, GFP_KERNEL);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2077  		      fnw_sz = sz;
079c9534a96da9a Alan Cox           2012-02-28  2078  		      if (!fnw) {
079c9534a96da9a Alan Cox           2012-02-28  2079  			ret = -ENOMEM;
079c9534a96da9a Alan Cox           2012-02-28  2080  			goto reterr;
079c9534a96da9a Alan Cox           2012-02-28  2081  		      }
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2082  		      goto again;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2083  		    }
079c9534a96da9a Alan Cox           2012-02-28  2084  
079c9534a96da9a Alan Cox           2012-02-28  2085  		    if (!q)
079c9534a96da9a Alan Cox           2012-02-28  2086  		      func_table[i] = fj;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2087  		    /* copy data before insertion point to new location */
079c9534a96da9a Alan Cox           2012-02-28  2088  		    if (fj > funcbufptr)
079c9534a96da9a Alan Cox           2012-02-28  2089  			memmove(fnw, funcbufptr, fj - funcbufptr);
079c9534a96da9a Alan Cox           2012-02-28  2090  		    for (k = 0; k < j; k++)
079c9534a96da9a Alan Cox           2012-02-28  2091  		      if (func_table[k])
079c9534a96da9a Alan Cox           2012-02-28  2092  			func_table[k] = fnw + (func_table[k] - funcbufptr);
079c9534a96da9a Alan Cox           2012-02-28  2093  
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2094  		    /* copy data after insertion point to new location */
079c9534a96da9a Alan Cox           2012-02-28  2095  		    if (first_free > fj) {
079c9534a96da9a Alan Cox           2012-02-28  2096  			memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
079c9534a96da9a Alan Cox           2012-02-28  2097  			for (k = j; k < MAX_NR_FUNC; k++)
079c9534a96da9a Alan Cox           2012-02-28  2098  			  if (func_table[k])
079c9534a96da9a Alan Cox           2012-02-28  2099  			    func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
079c9534a96da9a Alan Cox           2012-02-28  2100  		    }
079c9534a96da9a Alan Cox           2012-02-28  2101  		    if (funcbufptr != func_buf)
079c9534a96da9a Alan Cox           2012-02-28  2102  		      kfree(funcbufptr);
079c9534a96da9a Alan Cox           2012-02-28  2103  		    funcbufptr = fnw;
079c9534a96da9a Alan Cox           2012-02-28  2104  		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
079c9534a96da9a Alan Cox           2012-02-28  2105  		    funcbufsize = sz;
079c9534a96da9a Alan Cox           2012-02-28  2106  		}
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2107  		/* finally insert item itself */
987bbe4f15e721c Jiri Slaby         2020-10-16  2108  		strcpy(func_table[i], kbs);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10  2109  		spin_unlock_irqrestore(&func_buf_lock, flags);
079c9534a96da9a Alan Cox           2012-02-28  2110  		break;
079c9534a96da9a Alan Cox           2012-02-28  2111  	}
079c9534a96da9a Alan Cox           2012-02-28  2112  	ret = 0;
079c9534a96da9a Alan Cox           2012-02-28  2113  reterr:
079c9534a96da9a Alan Cox           2012-02-28 @2114  	kfree(kbs);
079c9534a96da9a Alan Cox           2012-02-28  2115  	return ret;
079c9534a96da9a Alan Cox           2012-02-28  2116  }
079c9534a96da9a Alan Cox           2012-02-28  2117  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31955 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-10-19  8:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-16 12:24 [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl Jiri Slaby
2020-10-16 12:24 ` [PATCH 2/3] vt: keyboard, simplify vt_kdgkbsent Jiri Slaby
2020-10-16 12:24 ` [PATCH 3/3] vt: keyboard, extend func_buf_lock to readers Jiri Slaby
2020-10-16 13:20   ` Greg KH
2020-10-19  8:00     ` Jiri Slaby
2020-10-16 14:13 [PATCH 1/3] vt: keyboard, reorder user buffer handling in vt_do_kdgkb_ioctl kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.