briansmith / ring

Safe, fast, small crypto using Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for statically-linked musl libc Linux targets (-unknown-linux-musl)

briansmith opened this issue · comments

Add support for statically-linked musl libc Linux targets (-unknown-linux-musl)

Why is removing the libc crate dependency a goal ?

FYI - from updates on rust-lang/libc#659, getrandom is now available in libc on most Linux platforms. The holdout is not musl, but android/Bionic. I suggest decoupling the two parts of this issue an moving the getrandom portion into a separate bug.

More discussion in #935

@aig787's PR #1067 added the -musl targets for Linux x86_64 and i686 to CI/CD.

Still to do:

  • rust-lang/rust#70740 indicates that we need to verify that we're doing the right thing w.r.t. PIE (position independent code), especially when compiling the C and assembly code.
  • Add Aarch64 musl targets to CI/CD.
  • Minimize the dependencies installed. Currently the i686 job installs "libc6-dev-i386" and "gcc-multilib", but neither of those should be needed for -musl. (No longer relevant.)
  • rust-lang/cc-rs#436 indicates that we should be doing more sanity checks to make sure we're not using the wrong header files. e.g. statically asserting that sizeof(uint64_t) == 8.

rust-lang/rust#70740 indicates that we need to verify that we're doing the right thing w.r.t. PIE (position independent code), especially when compiling the C and assembly code.

See also rust-lang/cc-rs#165. We should have a step in CI/CD that verifies that we support PIE correctly.

  • Minimize the dependencies installed. Currently the i686 job installs "libc6-dev-i386" and "gcc-multilib", but neither of those should be needed for -musl.

I attempted to remove the gcc-multilib dependency but the build fails with:

 running "clang" "-O0" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "--target=i686-unknown-linux-musl" "-I" "include" "-Wall" "-Wextra" "-std=c1x" "-Wbad-function-cast" "-Wnested-externs" "-Wstrict-prototypes" "-pedantic" "-pedantic-errors" "-Wall" "-Wextra" "-Wcast-align" "-Wcast-qual" "-Wconversion" "-Wenum-compare" "-Wfloat-equal" "-Wformat=2" "-Winline" "-Winvalid-pch" "-Wmissing-field-initializers" "-Wmissing-include-dirs" "-Wredundant-decls" "-Wshadow" "-Wsign-compare" "-Wsign-conversion" "-Wundef" "-Wuninitialized" "-Wwrite-strings" "-fno-strict-aliasing" "-fvisibility=hidden" "-fstack-protector" "-g3" "-Werror" "-U_FORTIFY_SOURCE" "-c" "-o/home/travis/build/briansmith/ring/target/i686-unknown-linux-musl/debug/build/ring-bb6253d99512d637/out/aes_nohw.o" "crypto/fipsmodule/aes/aes_nohw.c"
  In file included from crypto/fipsmodule/aes/aes_nohw.c:15:
  In file included from include/GFp/aes.h:52:
  In file included from include/GFp/base.h:66:
  In file included from /usr/local/clang-7.0.0/lib/clang/7.0.0/include/stdint.h:63:
  /usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found
  #include <bits/libc-header-start.h>
           ^~~~~~~~~~~~~~~~~~~~~~~~~~

I doubt using gcc-multilib with musl is the right thing to do but I could be convinced otherwise. I'll try experimenting with using --nostdlibinc and/or -nostdlib but it isn't clear that musl libc supports that configuration either.

Help understanding and/or resolving this is appreciated. Otherwise, maybe this is a good motivation to get rid of all the remaining C code in ring.

I'll try experimenting with using --nostdlibinc and/or -nostdlib

I did the experiment and that seems like it will work fine. I actually had done the same something similar for wasm32-unknown already and I verified that the same works for musl, without gcc-multilib and libc6-dev-i386. I need to clean up the experiment before creating a PR for it.

PR #1118 makes progress here; see that PR for details.

Remaining work to be done:

  • Add static analysis to the build system that verifies that the tests do not link to any shared libraries.
  • Run the tests for -musl targets
  • Find a solution for x86_64 targets. I'm leaning towards merging PR #1111 so that we wouldn't have a real need for poly1305_vec.c, and then removing poly1305_vec.c. Then we can remove the exception for x86_64 targets in build.rs and we should be good to go.

PR #1133 shows how to use RUSTFLAGS="-Clink-self-contained=yes -Clinker=rust-lld" for linking al -musl targets. For x86_64 (only) we still need a sysroot with header files; for other architectures this should be working fine.

I doubt using gcc-multilib with musl is the right thing to do but I could be convinced otherwise. I'll try experimenting with using --nostdlibinc and/or -nostdlib but it isn't clear that musl libc supports that configuration either.
Help understanding and/or resolving this is appreciated. Otherwise, maybe this is a good motivation to get rid of all the remaining C code in ring.

Hi,
I'm not sure if it will solve this problem, but in case it can help: I have no problem compiling dependencies relying on rustls (and thus ring) for the x86_64-unknown-linux-musl target from a rust:latest Docker image by running apt update && apt install -y musl-tools (https://github.com/skerkour/archive/blob/4a408405978ae714a7be9e92e2105324339f1f7b/simpleserver-rs/Dockerfile#L8)

I'm not sure if it will solve this problem, but in case it can help: I have no problem compiling dependencies relying on rustls (and thus ring) for the x86_64-unknown-linux-musl target from a rust:latest Docker image by running apt update && apt install -y musl-tools (https://github.com/skerkour/archive/blob/4a408405978ae714a7be9e92e2105324339f1f7b/simpleserver-rs/Dockerfile#L8)

Are you then using the TARGET_CC=musl-gcc TARGET_AR=musl-ar or similar? Are you using RUSTFLAGS="-Clink-self-contained=yes -Clinker=rust-lld" for linking?

No flags are used, the build command is as simple as cargo build --target x86_64-unknown-linux-musl --release

Are those flags special ring requirements, or are they workarounds to have MUSL compile?

No flags are used, the build command is as simple as cargo build --target x86_64-unknown-linux-musl --release

Are those flags special ring requirements, or are they workarounds to have MUSL compile?

cc-rs will automatically use the musl tools (musl-cc) by default, so if you are happy with using musl-tools, then you will get the correct results.

If you want to use clang and rust-lld and "self contained" linking instead, then you do have to set up some things as described in ring's mk/cargo.sh.

Maybe I should change ring's CI/CD to test the "Just use the defaults" code path.

Just want to add that if static linking is the only cencern, I'm able to produce a static linked binary using RUSTFLAGS="-C target-feature=+crt-static" cargo build --target x86_64-unknown-linux-gnu --release with glibc. I only use a subset of functions of ring though (namely hmac). Not sure would it affect linking.

Hi @briansmith, any news on this issue?

This has been working for a long time, AFAICT. We have aarch64-unknown-linux-musl, armv7-unknown-linux-musleabihf, i686-unknown-linux-musl, and x86_64-unknown-linux-musl tested in every CI run.