LKML Archive on lore.kernel.org
 help / Atom feed
From: "Uecker, Martin" <Martin.Uecker@med.uni-goettingen.de>
To: "keescook@chromium.org" <keescook@chromium.org>
Cc: "torvalds@linux-foundation.org" <torvalds@linux-foundation.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: VLAs and security
Date: Mon, 3 Sep 2018 07:39:31 +0000
Message-ID: <1535960372.32005.1.camel@med.uni-goettingen.de> (raw)
In-Reply-To: <CAGXu5jJ7kGm-DGUB8uwwhd-Hv7i4WEcSKumTf2MBsj_-yzWcqg@mail.gmail.com>

Am Sonntag, den 02.09.2018, 10:40 -0700 schrieb Kees Cook:
> On Sun, Sep 2, 2018 at 1:08 AM, Uecker, Martin
> <Martin.Uecker@med.uni-goettingen.de> wrote:
> > I do not agree that VLAs are generally bad for security.
> > I think the opposite is true. A VLA with the right size
> > allows the compiler to automatically perform or insert
> > meaningful bounds checks, while a fixed upper bound does not.
> 
> While I see what you mean, the trouble is that the compiler has no
> idea what the upper bounds of the _available_ stack is. This means
> that a large VLA might allow code to read/write beyond the stack
> allocation, which also bypasses the "standard" stack buffer overflow
> checks. Additionally, VLAs bypass the existing stack-size checks we've
> added to the kernel.

Limiting the size of the VLA should be sufficient to avoid this.

I don't know about your specific stack-size checks
in the kernel, but for general programming, the full solution
is for the compiler to probe the stack when growing.

But I was not talking about the bounds of the stack, but of the
array itself.

> > For example:
> > 
> > char buf[N];
> > buf[n] = 1;
> > 
> > Here, a compiler / analysis tool can for  n < N  using
> > static analysis or insert a run-time check.
> > 
> > Replacing this with
> > 
> > char buf[MAX_SIZE]
> > 
> > hides the information about the true upper bound
> > from automatic tools.
> 
> While this may be true for some tools, I don't agree VLAs are better
> in general. For example, the compiler actually knows the upper bound
> at build time now, and things like the printf format size checks and
> CONFIG_FORTIFY_SOURCE are now able to produce compile-time warnings
> (since "sizeof(buf)" isn't a runtime value). With a VLA, this is
> hidden from those tools, and detection depends on runtime analysis.

If the correct bound is actually a constant and the array
only ends up being a VLA for some random reason, I fully agree.

But if the true bound is smaller, then IMHO it is really bad advise
to tell programmers to use

char buf[MAX_SIZE]

instead of something like

assert(N <= MAX_SIZE); 
char buf[N]

because then errors of the form 

buf[n] = 1

with N < n < MAX_SIZE can not be detected anymore. Also the
code usually ends up being less readable, which is also a clear
disadvantage in my opinion.


> It should be noted that VLAs are also slow[1], so removing them not
> only improves robustness but also improves performance.

I have to admit that I am always a bit skeptical if somebody makes
generic claims such as "VLAs are slow" and then cites only a
single example. But I am not too surprised if compilers produce
crappy code for VLAs and that this can hurt performance in some
examples. But compared to dynamic allocation VLAs should be much
faster. They also reduce stack usage compared to always allocating
array with a fixed maximum size on the stack.

> > Of course, having predictable stack usage might be more
> > important in the kernel and might be a good argument
> > to still prefer the constant bound.
> 
> Between improved compile-time checking, faster runtime performance,
> and improved robustness against stack exhaustion, I strongly believe
> the kernel to be better off with VLAs entirely removed. And we are
> close: only 6 remain (out of the 115 I counted in v4.15).

Looking at some of the patches, I would say it is not 
clear to me that this is alway an improvement.

> > But loosing the tighter bounds is clearly a disadvantage
> > with respect to security that one should keep it mind.
> 
> Yes: without VLAs, stack array usage is reduced to "standard" stack
> buffer overflow concerns. Removing the VLA doesn't introduce a new
> risk: we already had to worry about fixed-size arrays. Removing VLAsalways
> means we don't have to worry about the VLA-specific risks anymore.

It introduces the new risk that certain logic error can
not be detected anymore by static analysis or run-time bounds
checking.

Best,
Martin

  reply index

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-02  8:08 Uecker, Martin
2018-09-02 17:40 ` Kees Cook
2018-09-03  7:39   ` Uecker, Martin [this message]
2018-09-03 21:28     ` Linus Torvalds
2018-09-04  6:27       ` Uecker, Martin
2018-09-04  8:00         ` Dmitry Vyukov
2018-09-04 18:22           ` Uecker, Martin
2018-09-05  7:35             ` Dmitry Vyukov

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1535960372.32005.1.camel@med.uni-goettingen.de \
    --to=martin.uecker@med.uni-goettingen.de \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org linux-kernel@archiver.kernel.org
	public-inbox-index lkml


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox