Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable full RELRO by default, expose in std.build #11825

Merged
merged 2 commits into from
Jun 8, 2022

Conversation

ifreund
Copy link
Member

@ifreund ifreund commented Jun 8, 2022

Full RELRO is a hardening feature that makes it impossible to perform
certian attacks involving overwriting parts of the Global Offset Table
to invoke arbitrary code.

It requires all symbols to be resolved before execution of the program
starts which may have an impact on startup time. However most if
not all popular Linux distributions enable full RELRO by default for
all binaries and this does not seem to make a noticeable difference
in practice.

"Partial RELRO" is equivalent to -z relro -z lazy.
"Full RELRO" is equivalent to -z relro -z now.

LLD defaults to -z relro -z lazy, which means Zig's current -z relro
option has no effect on LLD's behavior.

The changes made by this commit are as follows:

  • Document that -z relro is the default and add -z norelro.
  • Pass -z now to LLD by default to enable full RELRO by default.
  • Add -z lazy to disable passing -z now.

This was prompted by Arch Linux maintainers asking me how to enable RELRO for my software.
Closes #6977

Full RELRO is a hardening feature that makes it impossible to perform
certian attacks involving overwriting parts of the Global Offset Table
to invoke arbitrary code.

It requires all symbols to be resolved before execution of the program
starts which may have an impact on startup time. However most if
not all popular Linux distributions enable full RELRO by default for
all binaries and this does not seem to make a noticeable difference
in practice.

"Partial RELRO" is equivalent to `-z relro -z lazy`.
"Full RELRO" is equivalent to `-z relro -z now`.

LLD defaults to `-z relro -z lazy`, which means Zig's current `-z relro`
option has no effect on LLD's behavior.

The changes made by this commit are as follows:

- Document that `-z relro` is the default and add `-z norelro`.
- Pass `-z now` to LLD by default to enable full RELRO by default.
- Add `-z lazy` to disable passing `-z now`.
@daurnimator
Copy link
Collaborator

Closes #6977

I think this only partially closes it? Wouldn't we also need to update our loader (when not linking libc?)

@ifreund
Copy link
Member Author

ifreund commented Jun 8, 2022

I think this only partially closes it? Wouldn't we also need to update our loader (when not linking libc?)

Do you mean std.DynLib? It doesn't look like ElfDynLib supports relocations in the first place or for that matter much of anything.

I'm not sure it makes sense for ElfDynLib to exist in the first place to be honest. I don't think dynamic linking without linking libc makes sense. That leaves the use-case of using ElfDynLib to dynamically load symbols from a statically linked binary, which I think makes even less sense. Here's a mail with Rick Felker's thoughts on the subject (the primary author of musl libc).

@andrewrk
Copy link
Member

andrewrk commented Jun 8, 2022

ElfDynLib is old and experimental and will probably get removed from the standard library

@andrewrk andrewrk merged commit f5d97e5 into ziglang:master Jun 8, 2022
@ifreund ifreund deleted the std-build-relro branch June 8, 2022 19:49
@OfekShilon
Copy link

Why not build with -no-plt instead? Always seemed funny to me to erect the entire PLT apparatus to support lazy loading and then populate it at program startup. -no-plt is documented to be more efficient, and achieves the same effect (unless I'm missing some tradeoff)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support RELRO
4 participants