Eyra does the impossible
Eyra is challenging ideas about what it means to be a libc. In doing so, it's doing a few things often considered to be... impossible 😉.
rust-lang/rust#27970 is a soundness bug in Rust. It is a way that Rust programs
can segfault without using any
unsafe code. The bug was opened 8 years ago,
and it's widely believed to be impossible to fully fix.
One of the reasons it's so difficult is that it isn't enough to do locking,
even inside libc, because
getenv returns pointers to memory that need to stay
valid after the
getenv call returns. And,
setenv/etc. can be called
by arbitrary C code, so any scheme that relies on all callers of
following a particular protocol isn't reliable.
Eyra solves this by having
setenv etc. just leak the old memory. That ensures
that it stays valid for as long as any thread needs it. Granted, leaking isn't
great, and Eyra makes it configurable with the "threadsafe-setenv" cargo feature,
so it can be disabled in favor of the thread-unsafe implementation. However that
said, leaking is not unsafe, and for some use cases, it'll be less bad than
the possibility of undefined behavior from dangling pointers.
Eyra currently only supports Linux, and has other limitations, so it isn't a full solution for all of Rust, but it does solve the problem within its range.
Full host NSS and DNS support without dynamic linking
In glibc, a statically-linked binary, despite being statically linked,
heroically includes the ability to
dlopen NSS libraries as needed in order
to implement the lookup rules defined in "/etc/nsswitch.conf", and this means
that statically-linked binaries end up depending on the versions of the NSS
libraries that match the glibc version they were built with.
In musl, a statically-linked binary just hard-codes the basic NSS and DNS resolution strategies. It knows how to read "/etc/passwd", "/etc/resolv.conf", and other files, and do the main things that one does with those files, so it doesn't respect "/etc/nsswitch.conf" at all, and doesn't use the same name lookup logic as other programs on a glibc-based distribution.
These have long been the only options, but Eyra does something different.
In Eyra, NSS functions are implemented by executing the external
program, and parsing its output.
getent is present on both
musl-based Linux distributions, and has a stable command-line interface,
so Eyra programs do not depend on a specific version of libc being installed,
and it follows the system NSS and DNS configuration.
(And to be sure, using
getent like this won't work for all use cases, so
Eyra may add other options in the future.)
Compiling whole programs with a single
Eyra is not the only system capable of whole-program optimization, however to
my knowledge, it is the only system that can compile a whole program, entirely
from source, in a single
cargo build invocation.
This is achieved by using cargo's
-Z build-std option, which builds libcore,
liballoc, libstd, and other Rust libraries from source, by using Eyra which
builds the libc implementation from source, and, for completeness, by disabling
"use-compiler-builtins" feature, which tells it to use its own
memcpy etc. instead of linking to Rust's prebuilt
compiler_builtins library. Thay way, everything down to the OS boundary is
just a cargo dependency built from source. See the all-from-source example
for more details.
This may be useful for doing whole-program static analysis, for using non-standard calling conventions, or anything else that requires that the whole program be compiled together.
Eyra is currently a side project that I'm building for fun. If you think it sounds interesting, please reach out!