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

Support for Full RELRO #11046

Open
Blacksmoke16 opened this issue Jul 31, 2021 · 9 comments
Open

Support for Full RELRO #11046

Blacksmoke16 opened this issue Jul 31, 2021 · 9 comments

Comments

@Blacksmoke16
Copy link
Member

Blacksmoke16 commented Jul 31, 2021

I was messing around with adding a package to AUR and noticed namcap was producing a warning: ELF file ('usr/bin/oq') lacks FULL RELRO, check LDFLAGS, which apparently relates to an ELF hardening feature:

It seems this feature is enabled by default in Rust since Oct 2017. Probably wouldn't hurt to do the same in Crystal land? Could reference this PR: rust-lang/rust#43170.

@ysbaddaden
Copy link
Contributor

I just got the issue in NetBSD 10.0 where RELRO got enabled.

I could compile the crystal compiler itself (from a cross compiled & linked bootstrap) without any issues, but trying to compile the std specs, I ran into runtime missing symbols because of RELRO (missing xmlXYZ or _unwindXYZ symbol). It took me a while to notice that the llvm-config script was the one injecting -zrelro.

Apparently we usually support RELRO, but it seems that some external libraries may not be compatible?

I can enforce -Wl,-znorelro for NetBSD for a quick fixup, but that seems overkill. Maybe the @[Link] annotation for lib bindings could tell when they don't support RELRO? Then we could consider to enable or disable RELRO (partial or full) when invoking the linker just like we enable PIE?

Note: it may be something entirely different. We should verify the behavior on different platforms.

@straight-shoota
Copy link
Member

Wouldn't RELRO support be something that pkgconfig should know about? 🤔
AFAIU this is a property of a particular lib build (the binary) and can hardly be expressed in general terms for all variants of the library (the header)?

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 22, 2024

RELRO is a property of the final executable, set by the linker, just like PIE. Libraries may not be compatible for different reasons. At least this is how the pkgsrc treats it in NetBSD: https://www.netbsd.org/docs/pkgsrc/hardening.html

Searching RELRO_SUPPORTED in https://github.com/NetBSD/pkgsrc I notice that RELRO is disabled for Gcc, Zig, Rust and Go (even disabled by default for all Go applications).

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 22, 2024

Something very weird is that I could compile a Crystal compiler with RELRO but trying to compiler std_spec eventually failed because of the _Unwind_Backtrace symbol... but the compiler is raising exceptions and it must call this function, and thus need to access the same symbol, but in that case there was no error.

There's something fishy. Maybe it's another library that gets linked in that's creating issues.

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 22, 2024

Today the std specs compiled in my NetBSD 10.0 VM with -zrelro 🙃

EDIT: and suddenly linking fails 🙃

@ysbaddaden
Copy link
Contributor

Oh my: if crystal runs the cc command then the executable fails to run with missing symbols but if I pass --cross-compile then copy-paste the cc command and run it in the shell then the executable runs with RELRO enabled 🤔

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 22, 2024

Nope, I only get the above issue when I link std_spec from crystal on NetBSD. Compiling something has no issues, even when I pass --link-flags="-Wl,-zrelro,-znow" to force full RELRO.

I tried on Ubuntu 22.04, and I can compile and run std_spec with the above link flags without any issues.

Except for some corner cases on some platforms, it seems that Crystal is compatible with full RELRO 🤷

@ysbaddaden
Copy link
Contributor

ysbaddaden commented Oct 22, 2024

Oh, the link issue on netbsd disappears if I use --single-module! That explains why --cross-compile then calling cc worked, and why I could get a bootstrap crystal to recompile itself: they all generate a single object file!

straight-shoota pushed a commit that referenced this issue Oct 23, 2024
The LibC bindings for NetBSD were a bit wrong and some std specs also didn't work as expected. The segfault handler is also broken on NetBSD (the process crashes with SIGILL after receiving SIGSEGV).

With these fixes + pending specs I can run the std and compiler test suites in a NetBSD 10.0 VM.

**Caveat**: the pkgsrc for LLVM enforces partial RELRO and linking the std specs from crystal fails. You must pass `--single-module` for the executable to be able to start without missing runtime symbols from libxml2. See #11046.
@ysbaddaden
Copy link
Contributor

I'm running the Pop! OS flavor of Ubuntu 22.04 with LLVM 18 and CC points to GCC 11 (system default):

$ make .build/crystal
$ readelf -a .build/crystal | egrep 'RELRO|BIND_NOW'
  GNU_RELRO      0x0000000001ad66d0 0x0000000001ad86d0 0x0000000001ad86d0
 0x000000000000001e (FLAGS)              BIND_NOW

From the hardening pkgsrc page from NetBSD, it means that full RELRO has been enabled. Passing --link-flags=-v when building I see that the linker is invoked with -pie -znow -zrelro which indeed enables PIE and full RELRO.

So: Crystal supports full RELRO, with maybe some caveat (e.g. --single-module on NetBSD 10).

I guess there are little to no reasons to not enable the feature by default... but maybe it's already enabled system wide today (as is the case on Ubuntu 22.04 apparently).

CTC97 pushed a commit to CTC97/crystal that referenced this issue Nov 9, 2024
The LibC bindings for NetBSD were a bit wrong and some std specs also didn't work as expected. The segfault handler is also broken on NetBSD (the process crashes with SIGILL after receiving SIGSEGV).

With these fixes + pending specs I can run the std and compiler test suites in a NetBSD 10.0 VM.

**Caveat**: the pkgsrc for LLVM enforces partial RELRO and linking the std specs from crystal fails. You must pass `--single-module` for the executable to be able to start without missing runtime symbols from libxml2. See crystal-lang#11046.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants