unofficial mirror of libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Florian Weimer <fweimer@redhat.com>
To: "Zack Weinberg" <zack@owlfolio.org>
Cc: <libc-alpha@sourceware.org>
Subject: Re: Maybe we should get rid of ifuncs
Date: Tue, 23 Apr 2024 20:54:17 +0200	[thread overview]
Message-ID: <87cyqfc3l2.fsf@oldenburg.str.redhat.com> (raw)
In-Reply-To: <D0RPG6348D0S.1F9SCYCGKZ3VI@owlfolio.org> (Zack Weinberg's message of "Tue, 23 Apr 2024 14:14:23 -0400")

* Zack Weinberg:

> I've been thinking about the XZ exploit (two versions of the compression
> library `liblzma` included Trojan horse code that injected a back
> door into sshd; see https://research.swtch.com/xz-timeline) and what
> it means for glibc, and what I've come to is we should reconsider the
> entire idea of ifuncs.
>
> The SSH protocol does not use XZ compression.  liblzma.so was loaded
> into sshd's address space because some Linux distributions patched
> sshd to use libsystemd, and some libsystemd functions (having to do
> with systemd's "journal" logging subsystem, IIUC) do use liblzma, but
> by itself that wouldn't have been enough to give the exploit control,
> because the patched sshd doesn't use any of those functions.  But
> these same Linux distributions also compile libsshd with -z now
> (ironically, as a hardening measure, together with -z relro) and that
> means the resolvers for all the ifuncs in *all* the loaded shared
> libraries will be invoked, early enough in process startup that the
> PLT and GOT are still writable.  The XZ exploit used an ifunc resolver
> to rewrite a whole bunch of PLT entries, intercepting both calls
> within sshd proper, and calls from sshd to libcrypto.so
> (i.e. OpenSSL's general-purpose cryptography library).

GOT rewriting wasn't required.  OpenSSL itself has support for hooking
the relevant functions:

  <https://openssl.org/docs/man3.0/man3/RSA_set_method.html>

For some of the link orders I've seen, plain ELF symbol interposition
would have worked as well.  We don't know if such a thing gets detected
in practice.

> Ifuncs were already a problem -- resolvers are arbitrary application
> code that gets called from deep within the guts of the dynamic loader,
> possibly while internal locks are held (I don't know for sure).

Internal locks are held.  That also happens for ELF constructors (but is
perhaps fixable there).

> In -z now mode, they are called not just before the core C library is
> fully initialized, but before symbol resolution is complete, meaning
> that they can't necessarily make *any* function calls; we've had any
> number of bug reports about this.

We are getting closer to be able to fully initialize libc before IFUNC
resolvers run.  It should be a relatively short patch (a few dozen
lines), at least for Linux.  Since commit 78ca44da0160a0b442f ("elf:
Relocate libc.so early during startup and dlmopen (bug 31083)") we
already relocate libc out of order.

Beyond libc, there are still issues around symbol interposition (or
underlinking) and execution of IFUNC resolvers implemented in
yet-to-be-relocated shared objects.

In the other direction, I think it would be valuable to offer a mode
where we run ELF constructors when .data.rel.ro is still writable.

(In general, I'd be worried to chase last month's problem.)

> As far as I know, the only legitimate (non-malicious) use case anyone
> wants for ifuncs is to allow a library to select one of several
> implementations of a single function, based on the characteristics of
> the CPU -- such as how glibc itself selects the best available
> implementation of `memcpy` for the CPU.  It seems to me that we ought
> to be able to come up with a completely declarative mechanism for this
> use case.

Selection rules for string functions can be quite complicated, depending
not just on advertised CPU capabilities but also on CPU models (and
preferences derived from that).  For each new selection criteria, we'd
have to update glibc to implement it before it becomes usable by
applications.

I'm not sure how valuable it is to prevent code execution at the
relocation stage when a few microseconds later, the ELF constructor is
invoked, which by definition contains arbitrary code.

> And, in -z relro -z now mode, it would mean that no application code
> could run before the PLT and GOT are made read-only, closing the path
> that the XZ trojan used to hook itself into sshd.

It's possible to revert RELRO.  We do that for static dlopen on some
architectures (something that could be avoided with early libc
initialization described above).

Thanks,
Florian


  parent reply	other threads:[~2024-04-23 18:56 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-23 18:14 Maybe we should get rid of ifuncs Zack Weinberg
2024-04-23 18:39 ` enh
2024-04-23 19:46   ` Palmer Dabbelt
2024-04-24 13:56   ` Zack Weinberg
2024-04-24 14:25     ` enh
2024-04-23 18:52 ` Sam James
2024-04-23 18:54 ` Florian Weimer [this message]
2024-04-24 13:53   ` Zack Weinberg
2024-04-23 19:26 ` Andreas Schwab
2024-04-24 13:54   ` Zack Weinberg
2024-04-24  1:41 ` Richard Henderson
2024-04-24 14:43   ` Zack Weinberg
2024-04-24 15:09     ` enh
2024-04-28  0:24     ` Peter Bergner
2024-05-02  2:59       ` Michael Meissner
2024-04-30  8:42 ` Simon Josefsson

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

  List information: https://www.gnu.org/software/libc/involved.html

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

  git send-email \
    --in-reply-to=87cyqfc3l2.fsf@oldenburg.str.redhat.com \
    --to=fweimer@redhat.com \
    --cc=libc-alpha@sourceware.org \
    --cc=zack@owlfolio.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.
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 read-only IMAP folder(s) and NNTP newsgroup(s).