linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] efi: fix out-of-bounds null overwrite vulnerability
@ 2016-01-07 19:05 Insu Yun
  2016-01-08 10:13 ` Matt Fleming
  0 siblings, 1 reply; 7+ messages in thread
From: Insu Yun @ 2016-01-07 19:05 UTC (permalink / raw)
  To: matt, linux-efi, linux-kernel
  Cc: taesoo, yeongjin.jang, insu, changwoo, Insu Yun

snprintf's return value is not bound by size value.
(https://www.kernel.org/doc/htmldocs/kernel-api/API-snprintf.html)
if printed value is larger than buffer size, it can overwrite 
null byte in out-of-bounds buffer.

Signed-off-by: Insu Yun <wuninsu@gmail.com>
---
 drivers/firmware/efi/cper.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index d425374..77aa75f 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -267,7 +267,6 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
 			     "DIMM location: not present. DMI handle: 0x%.4x ",
 			     mem->mem_dev_handle);
 
-	msg[n] = '\0';
 	return n;
 }
 
-- 
1.9.1

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

* Re: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-07 19:05 [PATCH] efi: fix out-of-bounds null overwrite vulnerability Insu Yun
@ 2016-01-08 10:13 ` Matt Fleming
  2016-01-08 16:47   ` Luck, Tony
  0 siblings, 1 reply; 7+ messages in thread
From: Matt Fleming @ 2016-01-08 10:13 UTC (permalink / raw)
  To: Insu Yun
  Cc: linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo,
	Tony Luck

On Thu, 07 Jan, at 02:05:30PM, Insu Yun wrote:
> snprintf's return value is not bound by size value.
> (https://www.kernel.org/doc/htmldocs/kernel-api/API-snprintf.html)
> if printed value is larger than buffer size, it can overwrite 
> null byte in out-of-bounds buffer.
 
But this function doesn't use snprintf(), it uses scnprintf() which
returns the number of characters written into buf and, because
scnprintf() largely follows vnsprintf(), it will never write more than
'size' bytes into the buffer.

> Signed-off-by: Insu Yun <wuninsu@gmail.com>
> ---
>  drivers/firmware/efi/cper.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index d425374..77aa75f 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -267,7 +267,6 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
>  			     "DIMM location: not present. DMI handle: 0x%.4x ",
>  			     mem->mem_dev_handle);
>  
> -	msg[n] = '\0';
>  	return n;
>  }
>  

Calling this a vulnerability is a little extreme. These fields come
from firmware and if you can't trust the firmware you've got bigger
issues.

I'm not even sure this is a bug. Tony?

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

* RE: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-08 10:13 ` Matt Fleming
@ 2016-01-08 16:47   ` Luck, Tony
  2016-01-11 14:16     ` Matt Fleming
  0 siblings, 1 reply; 7+ messages in thread
From: Luck, Tony @ 2016-01-08 16:47 UTC (permalink / raw)
  To: Matt Fleming, Insu Yun
  Cc: linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo

> But this function doesn't use snprintf(), it uses scnprintf() which
> returns the number of characters written into buf and, because
> scnprintf() largely follows vnsprintf(), it will never write more than
> 'size' bytes into the buffer.

        if (bank && device)
                n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);

That looks like "snprintf", not "scnprintf" to me :-)

What about using:

	msg[len] = '\0';

to guarantee NUL termination?

-Tony

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

* Re: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-08 16:47   ` Luck, Tony
@ 2016-01-11 14:16     ` Matt Fleming
  2016-01-11 18:16       ` Luck, Tony
  0 siblings, 1 reply; 7+ messages in thread
From: Matt Fleming @ 2016-01-11 14:16 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Insu Yun, linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo

On Fri, 08 Jan, at 04:47:17PM, Luck, Tony wrote:
> > But this function doesn't use snprintf(), it uses scnprintf() which
> > returns the number of characters written into buf and, because
> > scnprintf() largely follows vnsprintf(), it will never write more than
> > 'size' bytes into the buffer.
> 
>         if (bank && device)
>                 n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
> 
> That looks like "snprintf", not "scnprintf" to me :-)
 
Oops! Can you believe I looked at the wrong function?

> What about using:
> 
> 	msg[len] = '\0';
> 
> to guarantee NUL termination?

But that may leave garbage bytes in 'rcd_decode_str' in the case where
the string isn't as long as 'len'.

How about memset()'ing the buffer to zero and deleting the NUL
termination line?

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

* RE: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-11 14:16     ` Matt Fleming
@ 2016-01-11 18:16       ` Luck, Tony
  2016-01-14 11:12         ` Matt Fleming
  0 siblings, 1 reply; 7+ messages in thread
From: Luck, Tony @ 2016-01-11 18:16 UTC (permalink / raw)
  To: Matt Fleming
  Cc: Insu Yun, linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo

>> What about using:
>> 
>> 	msg[len] = '\0';
>> 
>> to guarantee NUL termination?
>
> But that may leave garbage bytes in 'rcd_decode_str' in the case where
> the string isn't as long as 'len'.
>
> How about memset()'ing the buffer to zero and deleting the NUL
> termination line?

Looks like overkill to me.  We only use this function in two places:

        if (cper_dimm_err_location(cmem, rcd_decode_str))
                trace_seq_printf(p, "%s", rcd_decode_str);

        if (cper_dimm_err_location(&cmem, rcd_decode_str))
                printk("%s%s\n", pfx, rcd_decode_str);

Neither would care if there were garbage after the NUL and before the
end of the rcd_decode_str[] array.

This buffer isn't visible to user space, so we aren't leaking data by having
garbage bytes after the NUL.

-Tony

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

* Re: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-11 18:16       ` Luck, Tony
@ 2016-01-14 11:12         ` Matt Fleming
  2016-01-15  2:06           ` Tony Luck
  0 siblings, 1 reply; 7+ messages in thread
From: Matt Fleming @ 2016-01-14 11:12 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Insu Yun, linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo

On Mon, 11 Jan, at 06:16:14PM, Luck, Tony wrote:
> >> What about using:
> >> 
> >> 	msg[len] = '\0';
> >> 
> >> to guarantee NUL termination?
> >
> > But that may leave garbage bytes in 'rcd_decode_str' in the case where
> > the string isn't as long as 'len'.
> >
> > How about memset()'ing the buffer to zero and deleting the NUL
> > termination line?
> 
> Looks like overkill to me.  We only use this function in two places:
> 
>         if (cper_dimm_err_location(cmem, rcd_decode_str))
>                 trace_seq_printf(p, "%s", rcd_decode_str);
> 
>         if (cper_dimm_err_location(&cmem, rcd_decode_str))
>                 printk("%s%s\n", pfx, rcd_decode_str);
> 
> Neither would care if there were garbage after the NUL and before the
> end of the rcd_decode_str[] array.
> 
> This buffer isn't visible to user space, so we aren't leaking data by having
> garbage bytes after the NUL.

What about *before* the NUL? That was the point I was trying to make.
If the string you print into the buffer isn't 'len' bytes in size the
buffer will look like,

  "DIMM location: Foo bar"<garbage.....>\0

Doing the memset() before the call to snprintf() guarantees this won't
happen and means you don't have to try and calculate where the NUL
needs to be placed.

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

* Re: [PATCH] efi: fix out-of-bounds null overwrite vulnerability
  2016-01-14 11:12         ` Matt Fleming
@ 2016-01-15  2:06           ` Tony Luck
  0 siblings, 0 replies; 7+ messages in thread
From: Tony Luck @ 2016-01-15  2:06 UTC (permalink / raw)
  To: Matt Fleming
  Cc: Insu Yun, linux-efi, linux-kernel, taesoo, yeongjin.jang, insu, changwoo

On Thu, Jan 14, 2016 at 3:12 AM, Matt Fleming <matt@codeblueprint.co.uk> wrote:
> What about *before* the NUL? That was the point I was trying to make.
> If the string you print into the buffer isn't 'len' bytes in size the
> buffer will look like,
>
>   "DIMM location: Foo bar<garbage.....>\0"

Doesn't that actually look like:

    "DIMM location: Foo bar\0<garbage.....>\0"

snprintf() will NUL terminate what it writes into the buffer
if the buffer is big enough for what you were trying to
write there.  The problem happens when what you want
to write is too big. Then you have

    "DIMM location: ReallyLongFoo AlsoBar"


at which point "msg[len] = '\0'; will zap that 'r'
at the end to make sure printk() will stop at the
end of the valid part of buffer.

-Tony

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

end of thread, other threads:[~2016-01-15  2:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-07 19:05 [PATCH] efi: fix out-of-bounds null overwrite vulnerability Insu Yun
2016-01-08 10:13 ` Matt Fleming
2016-01-08 16:47   ` Luck, Tony
2016-01-11 14:16     ` Matt Fleming
2016-01-11 18:16       ` Luck, Tony
2016-01-14 11:12         ` Matt Fleming
2016-01-15  2:06           ` Tony Luck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).