* [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 3/3] vt: keyboard, extend func_buf_lock to readers
@ 2020-10-16 14:43 kernel test robot
0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2020-10-16 14:43 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 12213 bytes --]
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20201016122412.31767-3-jslaby@suse.cz>
References: <20201016122412.31767-3-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:2033 vt_do_kdgkb_ioctl() warn: possible info leak 'func_copy'
Old smatch warnings:
drivers/tty/vt/keyboard.c:1914 vt_do_kdsk_ioctl() warn: potential spectre issue 'key_map' [r]
drivers/tty/vt/keyboard.c:2061 vt_do_kdgkb_ioctl() warn: potential spectre issue 'func_table' [r] (local cap)
drivers/tty/vt/keyboard.c:2070 vt_do_kdgkb_ioctl() warn: possible spectre second half. 'fj'
drivers/tty/vt/keyboard.c:2076 vt_do_kdgkb_ioctl() warn: possible spectre second half. 'fj'
drivers/tty/vt/keyboard.c:2095 vt_do_kdgkb_ioctl() warn: possible spectre second half. 'fj'
drivers/tty/vt/keyboard.c:2097 vt_do_kdgkb_ioctl() warn: possible spectre second half. 'fj'
drivers/tty/vt/keyboard.c:2123 vt_do_kdgkb_ioctl() error: uninitialized symbol 'kbs'.
vim +/func_copy +2033 drivers/tty/vt/keyboard.c
079c9534a96da9a Alan Cox 2012-02-28 1998
4d5d6cd424ed623 Jiri Slaby 2020-10-16 1999 /* FIXME: This one needs untangling */
079c9534a96da9a Alan Cox 2012-02-28 2000 int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
079c9534a96da9a Alan Cox 2012-02-28 2001 {
987bbe4f15e721c Jiri Slaby 2020-10-16 2002 char *kbs;
079c9534a96da9a Alan Cox 2012-02-28 2003 u_char *q;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2004 int sz, fnw_sz;
079c9534a96da9a Alan Cox 2012-02-28 2005 int delta;
079c9534a96da9a Alan Cox 2012-02-28 2006 char *first_free, *fj, *fnw;
079c9534a96da9a Alan Cox 2012-02-28 2007 int i, j, k;
079c9534a96da9a Alan Cox 2012-02-28 2008 int ret;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2009 unsigned long flags;
079c9534a96da9a Alan Cox 2012-02-28 2010
079c9534a96da9a Alan Cox 2012-02-28 2011 if (!capable(CAP_SYS_TTY_CONFIG))
079c9534a96da9a Alan Cox 2012-02-28 2012 perm = 0;
079c9534a96da9a Alan Cox 2012-02-28 2013
987bbe4f15e721c Jiri Slaby 2020-10-16 2014 if (get_user(i, &user_kdgkb->kb_func))
987bbe4f15e721c Jiri Slaby 2020-10-16 2015 return -EFAULT;
079c9534a96da9a Alan Cox 2012-02-28 2016
987bbe4f15e721c Jiri Slaby 2020-10-16 2017 i = array_index_nospec(i, MAX_NR_FUNC);
079c9534a96da9a Alan Cox 2012-02-28 2018
079c9534a96da9a Alan Cox 2012-02-28 2019 switch (cmd) {
ab8a5f48e9d7cc2 Jiri Slaby 2020-10-16 2020 case KDGKBSENT: {
ab8a5f48e9d7cc2 Jiri Slaby 2020-10-16 2021 /* size should have been a struct member */
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2022 char *func_copy;
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2023 ssize_t len = sizeof(user_kdgkb->kb_string);
987bbe4f15e721c Jiri Slaby 2020-10-16 2024
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2025 func_copy = kmalloc(len, GFP_KERNEL);
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2026 if (!func_copy)
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2027 return -ENOMEM;
987bbe4f15e721c Jiri Slaby 2020-10-16 2028
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2029 spin_lock_irqsave(&func_buf_lock, flags);
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2030 len = strlcpy(func_copy, func_table[i] ? : "", len);
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2031 spin_unlock_irqrestore(&func_buf_lock, flags);
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2032
4d5d6cd424ed623 Jiri Slaby 2020-10-16 @2033 ret = copy_to_user(user_kdgkb->kb_string, func_copy, len + 1) ?
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2034 -EFAULT : 0;
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2035
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2036 kfree(func_copy);
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2037
4d5d6cd424ed623 Jiri Slaby 2020-10-16 2038 return ret;
ab8a5f48e9d7cc2 Jiri Slaby 2020-10-16 2039 }
079c9534a96da9a Alan Cox 2012-02-28 2040 case KDSKBSENT:
987bbe4f15e721c Jiri Slaby 2020-10-16 2041 if (!perm)
987bbe4f15e721c Jiri Slaby 2020-10-16 2042 return -EPERM;
987bbe4f15e721c Jiri Slaby 2020-10-16 2043
987bbe4f15e721c Jiri Slaby 2020-10-16 2044 kbs = strndup_user(user_kdgkb->kb_string,
987bbe4f15e721c Jiri Slaby 2020-10-16 2045 sizeof(user_kdgkb->kb_string));
987bbe4f15e721c Jiri Slaby 2020-10-16 2046 if (IS_ERR(kbs))
987bbe4f15e721c Jiri Slaby 2020-10-16 2047 return PTR_ERR(kbs);
079c9534a96da9a Alan Cox 2012-02-28 2048
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2049 fnw = NULL;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2050 fnw_sz = 0;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2051 /* race aginst other writers */
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2052 again:
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2053 spin_lock_irqsave(&func_buf_lock, flags);
079c9534a96da9a Alan Cox 2012-02-28 2054 q = func_table[i];
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2055
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2056 /* fj pointer to next entry after 'q' */
079c9534a96da9a Alan Cox 2012-02-28 2057 first_free = funcbufptr + (funcbufsize - funcbufleft);
079c9534a96da9a Alan Cox 2012-02-28 2058 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
079c9534a96da9a Alan Cox 2012-02-28 2059 ;
079c9534a96da9a Alan Cox 2012-02-28 2060 if (j < MAX_NR_FUNC)
079c9534a96da9a Alan Cox 2012-02-28 2061 fj = func_table[j];
079c9534a96da9a Alan Cox 2012-02-28 2062 else
079c9534a96da9a Alan Cox 2012-02-28 2063 fj = first_free;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2064 /* buffer usage increase by new entry */
987bbe4f15e721c Jiri Slaby 2020-10-16 2065 delta = (q ? -strlen(q) : 1) + strlen(kbs);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2066
079c9534a96da9a Alan Cox 2012-02-28 2067 if (delta <= funcbufleft) { /* it fits in current buf */
079c9534a96da9a Alan Cox 2012-02-28 2068 if (j < MAX_NR_FUNC) {
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2069 /* make enough space for new entry@'fj' */
079c9534a96da9a Alan Cox 2012-02-28 2070 memmove(fj + delta, fj, first_free - fj);
079c9534a96da9a Alan Cox 2012-02-28 2071 for (k = j; k < MAX_NR_FUNC; k++)
079c9534a96da9a Alan Cox 2012-02-28 2072 if (func_table[k])
079c9534a96da9a Alan Cox 2012-02-28 2073 func_table[k] += delta;
079c9534a96da9a Alan Cox 2012-02-28 2074 }
079c9534a96da9a Alan Cox 2012-02-28 2075 if (!q)
079c9534a96da9a Alan Cox 2012-02-28 2076 func_table[i] = fj;
079c9534a96da9a Alan Cox 2012-02-28 2077 funcbufleft -= delta;
079c9534a96da9a Alan Cox 2012-02-28 2078 } else { /* allocate a larger buffer */
079c9534a96da9a Alan Cox 2012-02-28 2079 sz = 256;
079c9534a96da9a Alan Cox 2012-02-28 2080 while (sz < funcbufsize - funcbufleft + delta)
079c9534a96da9a Alan Cox 2012-02-28 2081 sz <<= 1;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2082 if (fnw_sz != sz) {
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2083 spin_unlock_irqrestore(&func_buf_lock, flags);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2084 kfree(fnw);
079c9534a96da9a Alan Cox 2012-02-28 2085 fnw = kmalloc(sz, GFP_KERNEL);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2086 fnw_sz = sz;
079c9534a96da9a Alan Cox 2012-02-28 2087 if (!fnw) {
079c9534a96da9a Alan Cox 2012-02-28 2088 ret = -ENOMEM;
079c9534a96da9a Alan Cox 2012-02-28 2089 goto reterr;
079c9534a96da9a Alan Cox 2012-02-28 2090 }
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2091 goto again;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2092 }
079c9534a96da9a Alan Cox 2012-02-28 2093
079c9534a96da9a Alan Cox 2012-02-28 2094 if (!q)
079c9534a96da9a Alan Cox 2012-02-28 2095 func_table[i] = fj;
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2096 /* copy data before insertion point to new location */
079c9534a96da9a Alan Cox 2012-02-28 2097 if (fj > funcbufptr)
079c9534a96da9a Alan Cox 2012-02-28 2098 memmove(fnw, funcbufptr, fj - funcbufptr);
079c9534a96da9a Alan Cox 2012-02-28 2099 for (k = 0; k < j; k++)
079c9534a96da9a Alan Cox 2012-02-28 2100 if (func_table[k])
079c9534a96da9a Alan Cox 2012-02-28 2101 func_table[k] = fnw + (func_table[k] - funcbufptr);
079c9534a96da9a Alan Cox 2012-02-28 2102
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2103 /* copy data after insertion point to new location */
079c9534a96da9a Alan Cox 2012-02-28 2104 if (first_free > fj) {
079c9534a96da9a Alan Cox 2012-02-28 2105 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
079c9534a96da9a Alan Cox 2012-02-28 2106 for (k = j; k < MAX_NR_FUNC; k++)
079c9534a96da9a Alan Cox 2012-02-28 2107 if (func_table[k])
079c9534a96da9a Alan Cox 2012-02-28 2108 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
079c9534a96da9a Alan Cox 2012-02-28 2109 }
079c9534a96da9a Alan Cox 2012-02-28 2110 if (funcbufptr != func_buf)
079c9534a96da9a Alan Cox 2012-02-28 2111 kfree(funcbufptr);
079c9534a96da9a Alan Cox 2012-02-28 2112 funcbufptr = fnw;
079c9534a96da9a Alan Cox 2012-02-28 2113 funcbufleft = funcbufleft - delta + sz - funcbufsize;
079c9534a96da9a Alan Cox 2012-02-28 2114 funcbufsize = sz;
079c9534a96da9a Alan Cox 2012-02-28 2115 }
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2116 /* finally insert item itself */
987bbe4f15e721c Jiri Slaby 2020-10-16 2117 strcpy(func_table[i], kbs);
46ca3f735f345c9 Sergei Trofimovich 2019-03-10 2118 spin_unlock_irqrestore(&func_buf_lock, flags);
079c9534a96da9a Alan Cox 2012-02-28 2119 break;
079c9534a96da9a Alan Cox 2012-02-28 2120 }
079c9534a96da9a Alan Cox 2012-02-28 2121 ret = 0;
079c9534a96da9a Alan Cox 2012-02-28 2122 reterr:
079c9534a96da9a Alan Cox 2012-02-28 2123 kfree(kbs);
079c9534a96da9a Alan Cox 2012-02-28 2124 return ret;
079c9534a96da9a Alan Cox 2012-02-28 2125 }
079c9534a96da9a Alan Cox 2012-02-28 2126
---
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:43 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.