public inbox for linux-serial@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] vt: Fix potential read overflow of kernel memory
@ 2023-08-30 16:04 Azeem Shaikh
  2023-08-30 17:57 ` Greg Kroah-Hartman
  2023-08-30 19:27 ` Kees Cook
  0 siblings, 2 replies; 13+ messages in thread
From: Azeem Shaikh @ 2023-08-30 16:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-hardening, Azeem Shaikh, linux-kernel, linux-serial,
	Kefeng Wang, Andrew Morton

strlcpy() reads the entire source buffer first.
This read may exceed the destination size limit if
a source string is not NUL-terminated [1].

The copy_to_user() call uses @len returned from strlcpy() directly
without checking its value. This could potentially lead to read
overflow.

In an effort to remove strlcpy() completely [2], replace
strlcpy() here with strscpy().

[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
[2] https://github.com/KSPP/linux/issues/89

Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
---
 drivers/tty/vt/keyboard.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 358f216c6cd6..15359c328a23 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -2079,12 +2079,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
 			return -ENOMEM;

 		spin_lock_irqsave(&func_buf_lock, flags);
-		len = strlcpy(kbs, func_table[kb_func] ? : "", len);
+		len = strscpy(kbs, func_table[kb_func] ? : "", len);
 		spin_unlock_irqrestore(&func_buf_lock, flags);

+		if (len < 0) {
+			ret = -EFAULT;
+			break;
+		}
 		ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
 			-EFAULT : 0;
-
 		break;
 	}
 	case KDSKBSENT:
--
2.42.0.rc2.253.gd59a3bf2b4-goog



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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 16:04 [PATCH] vt: Fix potential read overflow of kernel memory Azeem Shaikh
@ 2023-08-30 17:57 ` Greg Kroah-Hartman
  2023-08-30 19:25   ` Azeem Shaikh
  2023-08-30 19:27 ` Kees Cook
  1 sibling, 1 reply; 13+ messages in thread
From: Greg Kroah-Hartman @ 2023-08-30 17:57 UTC (permalink / raw)
  To: Azeem Shaikh
  Cc: Jiri Slaby, linux-hardening, linux-kernel, linux-serial,
	Kefeng Wang, Andrew Morton

On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
> strlcpy() reads the entire source buffer first.
> This read may exceed the destination size limit if
> a source string is not NUL-terminated [1].

But that's not the case here, right?  So your "potential read overflow"
isn't relevant here.

> The copy_to_user() call uses @len returned from strlcpy() directly
> without checking its value. This could potentially lead to read
> overflow.

But can it?  How?

Those are all hard-coded strings, in the kernel source, there is no
potential overflow here.

And you know the buffer size is correct as well.

So why even check?

> In an effort to remove strlcpy() completely [2], replace
> strlcpy() here with strscpy().
> 
> [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
> [2] https://github.com/KSPP/linux/issues/89
> 
> Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
> ---
>  drivers/tty/vt/keyboard.c |    7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index 358f216c6cd6..15359c328a23 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -2079,12 +2079,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
>  			return -ENOMEM;
> 
>  		spin_lock_irqsave(&func_buf_lock, flags);
> -		len = strlcpy(kbs, func_table[kb_func] ? : "", len);
> +		len = strscpy(kbs, func_table[kb_func] ? : "", len);
>  		spin_unlock_irqrestore(&func_buf_lock, flags);
> 
> +		if (len < 0) {
> +			ret = -EFAULT;
> +			break;
> +		}

Don't check for impossible things please.

thanks,

greg k-h

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 17:57 ` Greg Kroah-Hartman
@ 2023-08-30 19:25   ` Azeem Shaikh
  2023-08-30 21:28     ` Kees Cook
  0 siblings, 1 reply; 13+ messages in thread
From: Azeem Shaikh @ 2023-08-30 19:25 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Jiri Slaby, linux-hardening, linux-kernel, linux-serial,
	Kefeng Wang, Andrew Morton

On Wed, Aug 30, 2023 at 1:57 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
> > strlcpy() reads the entire source buffer first.
> > This read may exceed the destination size limit if
> > a source string is not NUL-terminated [1].
>
> But that's not the case here, right?  So your "potential read overflow"
> isn't relevant here.
>
> > The copy_to_user() call uses @len returned from strlcpy() directly
> > without checking its value. This could potentially lead to read
> > overflow.
>
> But can it?  How?
>

The case I was considering is when the null-terminated hardcoded
string @func_table[kb_func] has length @new_len > @len. In this case,
strlcpy() will assign @len = @new_len and copy_to_user() would read
@new_len from the kmalloc-ed memory of @len. This is the potential
read overflow I was referring to. Let me know if I'm mistaken.

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 16:04 [PATCH] vt: Fix potential read overflow of kernel memory Azeem Shaikh
  2023-08-30 17:57 ` Greg Kroah-Hartman
@ 2023-08-30 19:27 ` Kees Cook
  1 sibling, 0 replies; 13+ messages in thread
From: Kees Cook @ 2023-08-30 19:27 UTC (permalink / raw)
  To: Azeem Shaikh
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-hardening, linux-kernel,
	linux-serial, Kefeng Wang, Andrew Morton

On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
> strlcpy() reads the entire source buffer first.

Perhaps add:
"... and returns the size of the source string, not the destination
string, which can be accidentally misused."

> This read may exceed the destination size limit if
> a source string is not NUL-terminated [1].
> 
> The copy_to_user() call uses @len returned from strlcpy() directly
> without checking its value. This could potentially lead to read
> overflow.

Since the code as written today is "accidentally correct", it's worth
clarifying this: there is no existing bug, but as written it is very
fragile and specifically uses a strlcpy() result without sanity checking
and using it to copy to userspace. (This is the exact anti-pattern for
strlcpy(), and only because the source strings are known good is this
safe.)

> In an effort to remove strlcpy() completely [2], replace
> strlcpy() here with strscpy().
> 
> [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
> [2] https://github.com/KSPP/linux/issues/89
> 
> Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
> ---
>  drivers/tty/vt/keyboard.c |    7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index 358f216c6cd6..15359c328a23 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -2079,12 +2079,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
>  			return -ENOMEM;
> 
>  		spin_lock_irqsave(&func_buf_lock, flags);
> -		len = strlcpy(kbs, func_table[kb_func] ? : "", len);
> +		len = strscpy(kbs, func_table[kb_func] ? : "", len);
>  		spin_unlock_irqrestore(&func_buf_lock, flags);
> 
> +		if (len < 0) {
> +			ret = -EFAULT;

I think this should be -ENOSPC as EFAULT implies an actual memory fault.

> +			break;
> +		}
>  		ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
>  			-EFAULT : 0;
> -
>  		break;
>  	}
>  	case KDSKBSENT:
> --
> 2.42.0.rc2.253.gd59a3bf2b4-goog
> 
> 

Thanks for sticking with these refactorings; we're almost free from
strlcpy. :)

-Kees

-- 
Kees Cook

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 19:25   ` Azeem Shaikh
@ 2023-08-30 21:28     ` Kees Cook
  2023-08-30 23:17       ` Dan Raymond
  2023-08-31  5:32       ` Jiri Slaby
  0 siblings, 2 replies; 13+ messages in thread
From: Kees Cook @ 2023-08-30 21:28 UTC (permalink / raw)
  To: Azeem Shaikh
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-hardening, linux-kernel,
	linux-serial, Kefeng Wang, Andrew Morton

On Wed, Aug 30, 2023 at 03:25:54PM -0400, Azeem Shaikh wrote:
> On Wed, Aug 30, 2023 at 1:57 PM Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
> >
> > On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
> > > strlcpy() reads the entire source buffer first.
> > > This read may exceed the destination size limit if
> > > a source string is not NUL-terminated [1].
> >
> > But that's not the case here, right?  So your "potential read overflow"
> > isn't relevant here.
> >
> > > The copy_to_user() call uses @len returned from strlcpy() directly
> > > without checking its value. This could potentially lead to read
> > > overflow.
> >
> > But can it?  How?
> >
> 
> The case I was considering is when the null-terminated hardcoded
> string @func_table[kb_func] has length @new_len > @len. In this case,
> strlcpy() will assign @len = @new_len and copy_to_user() would read
> @new_len from the kmalloc-ed memory of @len. This is the potential
> read overflow I was referring to. Let me know if I'm mistaken.

First there is:

ssize_t len = sizeof(user_kdgkb->kb_string);

"struct user_kdgkb" is UAPI (therefore unlikely to change), and kb_string
is 512:

struct kbsentry {
        unsigned char kb_func;
        unsigned char kb_string[512];
};

Then we do:

                len = strlcpy(kbs, func_table[kb_func] ? : "", len);

This is the anti-pattern (take the length of the _source_) we need to
remove. However, func_table[] is made up of either %NUL-terminated
strings:

char func_buf[] = {
        '\033', '[', '[', 'A', 0, 
        '\033', '[', '[', 'B', 0, 
...
char *func_table[MAX_NR_FUNC] = {
        func_buf + 0,
        func_buf + 5,
...

Or a NULL address itself. The ?: operator handles the NULL case, so
"len" can only ever be 0 through the longest string in func_buf. So it's
what I'd call "accidentally correct". i.e. it's using a fragile
anti-pattern, but in this case everything is hard-coded and less than
512.

Regardless, we need to swap for a sane pattern, which you've done. But
the commit log is misleading, so it needs some more detail. :)

-Kees

-- 
Kees Cook

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 21:28     ` Kees Cook
@ 2023-08-30 23:17       ` Dan Raymond
  2023-08-30 23:48         ` Kees Cook
  2023-08-31  5:32       ` Jiri Slaby
  1 sibling, 1 reply; 13+ messages in thread
From: Dan Raymond @ 2023-08-30 23:17 UTC (permalink / raw)
  To: Kees Cook, Azeem Shaikh
  Cc: Greg Kroah-Hartman, Jiri Slaby, linux-hardening, linux-kernel,
	linux-serial, Kefeng Wang, Andrew Morton

>>>> The copy_to_user() call uses @len returned from strlcpy() directly
>>>> without checking its value. This could potentially lead to read
>>>> overflow.
>>>
>>> But can it?  How?
>>>
>>
>> The case I was considering is when the null-terminated hardcoded
>> string @func_table[kb_func] has length @new_len > @len. In this case,
>> strlcpy() will assign @len = @new_len and copy_to_user() would read
>> @new_len from the kmalloc-ed memory of @len. This is the potential
>> read overflow I was referring to. Let me know if I'm mistaken.
> 
> ..it's what I'd call "accidentally correct". i.e. it's using a fragile> anti-pattern, but in this case everything is hard-coded and less than
> 512.
> 
> Regardless, we need to swap for a sane pattern, which you've done. But
> the commit log is misleading, so it needs some more detail. :)
> 
> -Kees

In my opinion strlcpy() is being used correctly here as a defensive
precaution.  If the source string is larger than the destination buffer
it will truncate rather than corrupt kernel memory.  However the
return value of strlcpy() is being misused.  If truncation occurred
the copy_to_user() call will corrupt user memory instead.

I also agree that this is not currently a bug.  It is fragile and it
could break if someone added a very large string to the table.

Why not fix this by avoiding the redundant string copy?  How about
something like this:

ptr = func_table[kb_func] ? : "";
len = strlen(ptr);

if (len >= sizeof(user_kdgkb->kb_string))
	return -ENOSPC;

if (copy_to_user(user_kdgkb->kb_string, ptr, len + 1))
	return -EFAULT;

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 23:17       ` Dan Raymond
@ 2023-08-30 23:48         ` Kees Cook
  2023-08-31  5:45           ` Dan Raymond
  0 siblings, 1 reply; 13+ messages in thread
From: Kees Cook @ 2023-08-30 23:48 UTC (permalink / raw)
  To: Dan Raymond
  Cc: Azeem Shaikh, Greg Kroah-Hartman, Jiri Slaby, linux-hardening,
	linux-kernel, linux-serial, Kefeng Wang, Andrew Morton

On Wed, Aug 30, 2023 at 05:17:12PM -0600, Dan Raymond wrote:
> In my opinion strlcpy() is being used correctly here as a defensive
> precaution.  If the source string is larger than the destination buffer
> it will truncate rather than corrupt kernel memory.  However the
> return value of strlcpy() is being misused.  If truncation occurred
> the copy_to_user() call will corrupt user memory instead.
> 
> I also agree that this is not currently a bug.  It is fragile and it
> could break if someone added a very large string to the table.
> 
> Why not fix this by avoiding the redundant string copy?  How about
> something like this:
> 
> ptr = func_table[kb_func] ? : "";
> len = strlen(ptr);
> 
> if (len >= sizeof(user_kdgkb->kb_string))
> 	return -ENOSPC;
> 
> if (copy_to_user(user_kdgkb->kb_string, ptr, len + 1))
> 	return -EFAULT;

This would work if not for func_buf_lock. The bounce buffer is used to
avoid needing to hold the spin lock across copy_to_user.

-- 
Kees Cook

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 21:28     ` Kees Cook
  2023-08-30 23:17       ` Dan Raymond
@ 2023-08-31  5:32       ` Jiri Slaby
  2023-08-31 14:21         ` Azeem Shaikh
  2023-08-31 18:30         ` Kees Cook
  1 sibling, 2 replies; 13+ messages in thread
From: Jiri Slaby @ 2023-08-31  5:32 UTC (permalink / raw)
  To: Kees Cook, Azeem Shaikh
  Cc: Greg Kroah-Hartman, linux-hardening, linux-kernel, linux-serial,
	Kefeng Wang, Andrew Morton

On 30. 08. 23, 23:28, Kees Cook wrote:
> On Wed, Aug 30, 2023 at 03:25:54PM -0400, Azeem Shaikh wrote:
>> On Wed, Aug 30, 2023 at 1:57 PM Greg Kroah-Hartman
>> <gregkh@linuxfoundation.org> wrote:
>>>
>>> On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
>>>> strlcpy() reads the entire source buffer first.
>>>> This read may exceed the destination size limit if
>>>> a source string is not NUL-terminated [1].
>>>
>>> But that's not the case here, right?  So your "potential read overflow"
>>> isn't relevant here.
>>>
>>>> The copy_to_user() call uses @len returned from strlcpy() directly
>>>> without checking its value. This could potentially lead to read
>>>> overflow.
>>>
>>> But can it?  How?
>>>
>>
>> The case I was considering is when the null-terminated hardcoded
>> string @func_table[kb_func] has length @new_len > @len. In this case,
>> strlcpy() will assign @len = @new_len and copy_to_user() would read
>> @new_len from the kmalloc-ed memory of @len. This is the potential
>> read overflow I was referring to. Let me know if I'm mistaken.
> 
> First there is:
> 
> ssize_t len = sizeof(user_kdgkb->kb_string);
> 
> "struct user_kdgkb" is UAPI (therefore unlikely to change), and kb_string
> is 512:
> 
> struct kbsentry {
>          unsigned char kb_func;
>          unsigned char kb_string[512];
> };
> 
> Then we do:
> 
>                  len = strlcpy(kbs, func_table[kb_func] ? : "", len);
> 
> This is the anti-pattern (take the length of the _source_) we need to
> remove.

But len is the length of kbs, i.e. the destination. Or what am I missing?

                 kbs = kmalloc(len, GFP_KERNEL);
                 len = strlcpy(kbs, func_table[kb_func] ? : "", len);

> However, func_table[] is made up of either %NUL-terminated
> strings:
> 
> char func_buf[] = {
>          '\033', '[', '[', 'A', 0,
>          '\033', '[', '[', 'B', 0,
> ...
> char *func_table[MAX_NR_FUNC] = {
>          func_buf + 0,
>          func_buf + 5,
> ...
> 
> Or a NULL address itself. The ?: operator handles the NULL case, so
> "len" can only ever be 0 through the longest string in func_buf. So it's
> what I'd call "accidentally correct". i.e. it's using a fragile
> anti-pattern, but in this case everything is hard-coded and less than
> 512.
> 
> Regardless, we need to swap for a sane pattern, which you've done. But
> the commit log is misleading, so it needs some more detail. :)

I am still missing what is wrong in the above code with strlcpy(). The 
dest is deliberately made as long as the source, so the returned len is 
never less then the passed len. No checking needed IMO. Perhaps, we 
might switch to strcpy()?

FWIW I introduced this in commit 82e61c3909db5. So if it needs fixing, 
the patch deserves a Fixes: 82e61c3909db5 tag.

thanks,
-- 
js
suse labs


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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-30 23:48         ` Kees Cook
@ 2023-08-31  5:45           ` Dan Raymond
  2023-08-31 14:23             ` Azeem Shaikh
  0 siblings, 1 reply; 13+ messages in thread
From: Dan Raymond @ 2023-08-31  5:45 UTC (permalink / raw)
  To: Kees Cook
  Cc: Azeem Shaikh, Greg Kroah-Hartman, Jiri Slaby, linux-hardening,
	linux-kernel, linux-serial, Kefeng Wang, Andrew Morton

On 8/30/2023 5:48 PM, Kees Cook wrote:
> Warning: This email is from an unusual correspondent.
> Warning: Make sure this is someone you trust.
> 
> On Wed, Aug 30, 2023 at 05:17:12PM -0600, Dan Raymond wrote:
>> In my opinion strlcpy() is being used correctly here as a defensive
>> precaution.  If the source string is larger than the destination buffer
>> it will truncate rather than corrupt kernel memory.  However the
>> return value of strlcpy() is being misused.  If truncation occurred
>> the copy_to_user() call will corrupt user memory instead.
>>
>> I also agree that this is not currently a bug.  It is fragile and it
>> could break if someone added a very large string to the table.
>>
>> Why not fix this by avoiding the redundant string copy?  How about
>> something like this:
>>
>> ptr = func_table[kb_func] ? : "";
>> len = strlen(ptr);
>>
>> if (len >= sizeof(user_kdgkb->kb_string))
>> 	return -ENOSPC;
>>
>> if (copy_to_user(user_kdgkb->kb_string, ptr, len + 1))
>> 	return -EFAULT;
> 
> This would work if not for func_buf_lock. The bounce buffer is used to
> avoid needing to hold the spin lock across copy_to_user.
> 

Ah you're right.  Thanks for setting me straight.  Now I realize that my
entire assessment was wrong.  The original author was not using strlcpy()
as a defensive measure to prevent a buffer overflow.  He was using it so
that he could create a copy of the string and measure its length using
only one pass.  This minimizes the time spent holding the spinlock.

The surrounding code was written such that a buffer overflow is
impossible.  No additional checks are needed.  The proposed patch is
unnecessary.  But at least it preserves the spirit of the original
author's code by performing only one pass of the source string
while holding the spinlock.

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-31  5:32       ` Jiri Slaby
@ 2023-08-31 14:21         ` Azeem Shaikh
  2023-08-31 18:30         ` Kees Cook
  1 sibling, 0 replies; 13+ messages in thread
From: Azeem Shaikh @ 2023-08-31 14:21 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Kees Cook, Greg Kroah-Hartman, linux-hardening, linux-kernel,
	linux-serial, Kefeng Wang, Andrew Morton

On Thu, Aug 31, 2023 at 1:32 AM Jiri Slaby <jirislaby@kernel.org> wrote:
>
> On 30. 08. 23, 23:28, Kees Cook wrote:
> > On Wed, Aug 30, 2023 at 03:25:54PM -0400, Azeem Shaikh wrote:
> >> On Wed, Aug 30, 2023 at 1:57 PM Greg Kroah-Hartman
> >> <gregkh@linuxfoundation.org> wrote:
> >>>
> >>> On Wed, Aug 30, 2023 at 04:04:10PM +0000, Azeem Shaikh wrote:
> >>>> strlcpy() reads the entire source buffer first.
> >>>> This read may exceed the destination size limit if
> >>>> a source string is not NUL-terminated [1].
> >>>
> >>> But that's not the case here, right?  So your "potential read overflow"
> >>> isn't relevant here.
> >>>
> >>>> The copy_to_user() call uses @len returned from strlcpy() directly
> >>>> without checking its value. This could potentially lead to read
> >>>> overflow.
> >>>
> >>> But can it?  How?
> >>>
> >>
> >> The case I was considering is when the null-terminated hardcoded
> >> string @func_table[kb_func] has length @new_len > @len. In this case,
> >> strlcpy() will assign @len = @new_len and copy_to_user() would read
> >> @new_len from the kmalloc-ed memory of @len. This is the potential
> >> read overflow I was referring to. Let me know if I'm mistaken.
> >
> > First there is:
> >
> > ssize_t len = sizeof(user_kdgkb->kb_string);
> >
> > "struct user_kdgkb" is UAPI (therefore unlikely to change), and kb_string
> > is 512:
> >
> > struct kbsentry {
> >          unsigned char kb_func;
> >          unsigned char kb_string[512];
> > };
> >
> > Then we do:
> >
> >                  len = strlcpy(kbs, func_table[kb_func] ? : "", len);
> >
> > This is the anti-pattern (take the length of the _source_) we need to
> > remove.
>
> But len is the length of kbs, i.e. the destination. Or what am I missing?
>
>                  kbs = kmalloc(len, GFP_KERNEL);
>                  len = strlcpy(kbs, func_table[kb_func] ? : "", len);
>
> > However, func_table[] is made up of either %NUL-terminated
> > strings:
> >
> > char func_buf[] = {
> >          '\033', '[', '[', 'A', 0,
> >          '\033', '[', '[', 'B', 0,
> > ...
> > char *func_table[MAX_NR_FUNC] = {
> >          func_buf + 0,
> >          func_buf + 5,
> > ...
> >
> > Or a NULL address itself. The ?: operator handles the NULL case, so
> > "len" can only ever be 0 through the longest string in func_buf. So it's
> > what I'd call "accidentally correct". i.e. it's using a fragile
> > anti-pattern, but in this case everything is hard-coded and less than
> > 512.
> >
> > Regardless, we need to swap for a sane pattern, which you've done. But
> > the commit log is misleading, so it needs some more detail. :)
>
> I am still missing what is wrong in the above code with strlcpy(). The
> dest is deliberately made as long as the source, so the returned len is
> never less then the passed len. No checking needed IMO. Perhaps, we
> might switch to strcpy()?
>
> FWIW I introduced this in commit 82e61c3909db5. So if it needs fixing,
> the patch deserves a Fixes: 82e61c3909db5 tag.
>

As explained by Kees in previous comments, this is not actually a bug,
just a fragile anti-pattern. So we shouldn't need the Fixes: tag on
this patch.

> thanks,
> --
> js
> suse labs
>

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-31  5:45           ` Dan Raymond
@ 2023-08-31 14:23             ` Azeem Shaikh
  2023-09-15  2:56               ` Kees Cook
  0 siblings, 1 reply; 13+ messages in thread
From: Azeem Shaikh @ 2023-08-31 14:23 UTC (permalink / raw)
  To: Dan Raymond
  Cc: Kees Cook, Greg Kroah-Hartman, Jiri Slaby, linux-hardening,
	linux-kernel, linux-serial, Kefeng Wang, Andrew Morton

On Thu, Aug 31, 2023 at 1:45 AM Dan Raymond <draymond@foxvalley.net> wrote:
>
> On 8/30/2023 5:48 PM, Kees Cook wrote:
> > Warning: This email is from an unusual correspondent.
> > Warning: Make sure this is someone you trust.
> >
> > On Wed, Aug 30, 2023 at 05:17:12PM -0600, Dan Raymond wrote:
> >> In my opinion strlcpy() is being used correctly here as a defensive
> >> precaution.  If the source string is larger than the destination buffer
> >> it will truncate rather than corrupt kernel memory.  However the
> >> return value of strlcpy() is being misused.  If truncation occurred
> >> the copy_to_user() call will corrupt user memory instead.
> >>
> >> I also agree that this is not currently a bug.  It is fragile and it
> >> could break if someone added a very large string to the table.
> >>
> >> Why not fix this by avoiding the redundant string copy?  How about
> >> something like this:
> >>
> >> ptr = func_table[kb_func] ? : "";
> >> len = strlen(ptr);
> >>
> >> if (len >= sizeof(user_kdgkb->kb_string))
> >>      return -ENOSPC;
> >>
> >> if (copy_to_user(user_kdgkb->kb_string, ptr, len + 1))
> >>      return -EFAULT;
> >
> > This would work if not for func_buf_lock. The bounce buffer is used to
> > avoid needing to hold the spin lock across copy_to_user.
> >
>
> Ah you're right.  Thanks for setting me straight.  Now I realize that my
> entire assessment was wrong.  The original author was not using strlcpy()
> as a defensive measure to prevent a buffer overflow.  He was using it so
> that he could create a copy of the string and measure its length using
> only one pass.  This minimizes the time spent holding the spinlock.
>
> The surrounding code was written such that a buffer overflow is
> impossible.  No additional checks are needed.  The proposed patch is
> unnecessary.  But at least it preserves the spirit of the original
> author's code by performing only one pass of the source string
> while holding the spinlock.

Are folks ok with me sending out a v2 for this with a better commit
log that explains the issue?

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-31  5:32       ` Jiri Slaby
  2023-08-31 14:21         ` Azeem Shaikh
@ 2023-08-31 18:30         ` Kees Cook
  1 sibling, 0 replies; 13+ messages in thread
From: Kees Cook @ 2023-08-31 18:30 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Azeem Shaikh, Greg Kroah-Hartman, linux-hardening, linux-kernel,
	linux-serial, Kefeng Wang, Andrew Morton

On Thu, Aug 31, 2023 at 07:32:18AM +0200, Jiri Slaby wrote:
> On 30. 08. 23, 23:28, Kees Cook wrote:
> >                  len = strlcpy(kbs, func_table[kb_func] ? : "", len);
> > 
> > This is the anti-pattern (take the length of the _source_) we need to
> > remove.
> 
> But len is the length of kbs, i.e. the destination. Or what am I missing?

strlcpy() returns the length of the _source_ string (i.e. it could be
greater than the input argument len). But there is no current flaw here
(since all sources are very short). We're just trying to remove strlcpy()
since it leads to unexpected results.

-Kees

-- 
Kees Cook

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

* Re: [PATCH] vt: Fix potential read overflow of kernel memory
  2023-08-31 14:23             ` Azeem Shaikh
@ 2023-09-15  2:56               ` Kees Cook
  0 siblings, 0 replies; 13+ messages in thread
From: Kees Cook @ 2023-09-15  2:56 UTC (permalink / raw)
  To: Azeem Shaikh
  Cc: Dan Raymond, Greg Kroah-Hartman, Jiri Slaby, linux-hardening,
	linux-kernel, linux-serial, Kefeng Wang, Andrew Morton

On Thu, Aug 31, 2023 at 10:23:10AM -0400, Azeem Shaikh wrote:
> Are folks ok with me sending out a v2 for this with a better commit
> log that explains the issue?

Yes, please do. It should clear up the questions from this thread. :)

Thanks!

-Kees

-- 
Kees Cook

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

end of thread, other threads:[~2023-09-15  2:56 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-30 16:04 [PATCH] vt: Fix potential read overflow of kernel memory Azeem Shaikh
2023-08-30 17:57 ` Greg Kroah-Hartman
2023-08-30 19:25   ` Azeem Shaikh
2023-08-30 21:28     ` Kees Cook
2023-08-30 23:17       ` Dan Raymond
2023-08-30 23:48         ` Kees Cook
2023-08-31  5:45           ` Dan Raymond
2023-08-31 14:23             ` Azeem Shaikh
2023-09-15  2:56               ` Kees Cook
2023-08-31  5:32       ` Jiri Slaby
2023-08-31 14:21         ` Azeem Shaikh
2023-08-31 18:30         ` Kees Cook
2023-08-30 19:27 ` Kees Cook

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox