mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: Sergei Trofimovich <slyfox@gentoo.org>
Cc: musl@lists.openwall.com, libc-alpha@sourceware.org,
	gcc@gcc.gnu.org, toolchain@gentoo.org
Subject: Re: [musl] musl, glibc and ideal place for __stack_chk_fail_local
Date: Sat, 25 Jan 2020 10:54:24 -0500	[thread overview]
Message-ID: <20200125155424.GZ30412@brightrain.aerifal.cx> (raw)
In-Reply-To: <20200125105331.7c5d284b@sf>

On Sat, Jan 25, 2020 at 10:53:31AM +0000, Sergei Trofimovich wrote:
> [ sending it to musl, glibc and gcc devel mailing list as we need
>   to build a consensus across the projects ]
> 
> To support smash stack protection gcc emits __stack_chk_fail
> calls on all targets. On top of that gcc emits __stack_chk_fail_local
> calls at least on i386 and powerpc:
>     https://bugs.gentoo.org/706210#c9
> 
> gcc can either use libssp/libssp_nonshared fallback or rely on libc
> to provide __stack_chk_fail. Where ideally should gcc pick
> __stack_chk_fail_local?

*Ideally*, GCC would emit it as a linkonce function section in every
file that used it, the same way it does for __x86.get_pc_thunk.bx,
etc. But that's not going to happen in old GCC versions so it's not a
real solution even if new GCC were improved to do that.

Second-best would be for __stack_chk_fail_local to be in the
static-only part of libgcc. It's the same kind of compiler glue. This
is plausible to patch into any GCC version when building.

In reality, the path of least resistance is just continuing to have it
in libssp_nonshared.a; this is what all the distros do. All it
requires is patching the GCC specs so that -lssp_nonshared is always
passed.

> Looks like gcc/glibc and musl disagree on that:
> - gcc: gcc either provides it from libssp_nonshared.a if libc has
>   no ssp support or pulls it from libc
> - glibc: provides both __stack_chk_fail (deault) and
>   __stack_chk_fail_local (avoid PLT) symbols.
>   __stack_chk_fail_local comes from libc_nonshared.a and is
>   added to linker script as: $ cat /usr/lib/libc.so
>     OUTPUT_FORMAT(elf32-i386)
>     GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a  AS_NEEDED ( /lib/ld-linux.so.2 ) )

There's no good reason for it to come from a "nonshared" lib file
provided by libc rather than by the compiler. It's compiler ABI glue
between the public API/ABI (__stack_chk_fail) and the PIC callers that
don't want to be burdened by the GOT pointer setup to be able to call
thru PLT.

> - musl: provides only __stack_chk_fail (default) and
>   refuses to provide __stack_chk_fail_local:
>   https://www.openwall.com/lists/musl/2018/09/11/2

It's not that we refuse; it's that we can't, at least not without
gratuitously changing other things. libc.so can't be made a linker
script because then the real .so would have a different name and the
DT_NEEDED would thereby change. (No, libc.so can't use DT_SONAME to
control the name because then if you install /lib/ld-musl-$(ARCH).so.1
on a glibc-based system and run ldconfig, ldconfig will forcibly ln -s
ld-musl-$(ARCH).so.1 /lib/libc.so, which is A Bad Thing.)

There is a half-serious proposal to put it in crti.o which is always
linked too, but that seems like an ugly hack to me...

> This makes musl effectively not support ssp on i386 and probably powerpc.

It's working for all dists because we/they just make GCC pass
-lssp_nonshared via specs.

> Currently gcc's assumption is that musl supports ssp symbols
> from libc on all targets:
>    https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/configure.ac;h=a7521ee99436a7c12159bdde0471dc66d3c4288e;hb=HEAD#l6079
> 
>   6088     case "$target" in
>   6089        *-*-musl*)
>   6090          # All versions of musl provide stack protector
>   6091          gcc_cv_libc_provides_ssp=yes;;
> 
> Clearly that assumption is not correct as __stack_chk_fail_local
> is not provided by musl and linking fails.
> 
> This sounds like a expectation mismatch between gcc and musl
> of what it takes to implement an ssp interface.
> 
> What should we do to make it fixed long term and short term?
> 
> Long term:
> 
> Is there a vision of perfect end state agreed with gcc/glibc/musl
> folk so we could just implement it? If there is none let's try to
> form one.
> 
> My understanding of requirements for libc that exposes ssp support:
> - __stack_chk_fail is implemented as a default symbol
> - __stack_chk_fail_local is implemented as a local symbol to avoid PLT.
>   (Why is it important? To avoid use of potentially already broken stack?)

Because performance cost of -fstack-protector would go from 1-2% up to
5-10% on i386 and other archs where PLT contract requires a GOT
register, since loading the GOT register is expensive
(__x86.get_pc_thunk.* thunk itself is somewhat costly, and you throw
away one of only a small number of available registers, increasing
register pressure and hurting codegen).

> My understanding of possible perfect end state:
> 1. All libcs are required to somehow provide both __stack_chk_fail
>    and __stack_chk_fail_local: be it linker script, crt*.o files or an extra
>    libc_nonshared.a which gcc explicitly uses. Which one is best?
> 2. All libcs are required to provide only __stack_chk_fail and gcc always
>    provides __stack_chk_local from libgcc.a, or from new libgcc_ssp.a.
>    Evntually glibc drops it's __stack_chk_fail definition.
> 3. Your variant.
> 
> How do you gcc/glibc/musl folk see it? Once we decide I'll file bugs
> against agreed projects. At least gcc could explicitly document the
> interface.
> 
> Short term:
> 
> While the above is not addressed what should we do about musl in gcc?
> 
> Should gcc stop trying use musl on i386/powerpc here:
>   6088     case "$target" in
>   6089        *-*-musl*)
>   6090          # All versions of musl provide stack protector
>   6091          gcc_cv_libc_provides_ssp=yes;;
> and fall back to libssp instead?

Absolutely not. libssp is unsafe and creates new vulns/attack surface
by doing introspective stuff after the process is already *known to
be* in a compromised state. It should never be used. musl's
__stack_chk_fail is safe and terminates immediately.

The short term solution is just to continue what we're doing, adding
-lssp_nonshared to specs.

Ideally, though, GCC would just emit the termination inline (or at
least have an option to do so) rather than calling __stack_chk_fail or
the local version. This would additionally harden against the case
where the GOT is compromised.

Rich

  reply	other threads:[~2020-01-25 15:54 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-25 10:53 Sergei Trofimovich
2020-01-25 15:54 ` Rich Felker [this message]
2020-01-30 12:33   ` Segher Boessenkool
2020-01-30 13:37     ` Rich Felker
2020-01-30 14:56       ` Segher Boessenkool

Reply instructions:

You may reply publicly 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=20200125155424.GZ30412@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=gcc@gcc.gnu.org \
    --cc=libc-alpha@sourceware.org \
    --cc=musl@lists.openwall.com \
    --cc=slyfox@gentoo.org \
    --cc=toolchain@gentoo.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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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).