Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 19 Sep 2017 14:48:05 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: preventable SIGSEGV when bad AT_SYSINFO_EHDR

On Tue, Sep 19, 2017 at 07:21:29PM +0200, Markus Wichmann wrote:
> On Tue, Sep 19, 2017 at 09:46:19AM -0700, John Reiser wrote:
> > __dls3() and friends in musl/ldso/dynlink.c should check Elf headers more carefully.
> > I saw a SIGSEGV in decode_dyn() because vdso_base = ElfXX_auxv[{AT_SYSINFO_EHDR}].a_ptr
> > pointed to a region that was all zero, and thus vdso.dynv == 0.  The operating system
> > kernel is the only one who can perform a fork() or clone(), but other software can
> > perform execve().  In my case that other software had a bug.  However, the blame
> > for the SIGSEGV rests on __dls3() because it did not validate input data.  [This is
> > the stuff of exploits.]  Calling a_crash() is OK; but a preventable SIGSEGV must be
> > avoided, both directly and because it indicates a lack of secure implementation.
> > 
> 
> How esoteric.
> 
> As far as I know, the aux headers come from the kernel and are
> implicitly trusted because of that. If you have some userspace program
> trying to do execve() without a kernel call, then that program needs to
> correctly implement the aux headers. Mistrusting aux headers is as
> sensible as mistrusting the kernel. For example, we fetch our user
> credentials out of the aux headers in __init_libc().
> 
> But if your program emulates execve(), then how does security come into
> play here? Security is only important if security domains are switched,
> which a userspace program can't do (discounting kernel bugs, of course).
> And so you're left with a program that might be able to exploit musl
> into running arbitrary code in its own security domain. Newsflash: You
> can already run arbitrary code in your own security domain. It's called

This is pretty much the end of the story -- no crossing of privilege
domains takes place so there is no "untrusted input from outside the
privilege domain" to validate. Theoretically there's a huge amount of
initial environmental state provided by the kernel/program-loader to
the entry point, not just auxv, and aside from not giving you any new
security properties, maximally validating it would be a huge amount of
work, both implementation work and runtime work, and could still not
catch all possible invalid cases.

Pretty much the only time it does make sense to validate what the
kernel gives you is when there are known historical kernels or other
loaders (Linux or Linux-ABI-compat loaders in other operating systems
or emulators) with bugs that would cause program misbehavior. For
example, see commit 54482898abe8d6d937ee67ea5974cd8eae859c37 which
validates that AT_SYSINFO_EHDR is not just present but nonzero, since
Linux/s390x wrongly passes it but with a zero value.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.