From fbe47cec3d3ddc9cdc2ca9363d8f833d060369a1 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Fri, 18 Oct 2024 09:56:13 -0400 Subject: [PATCH] Dockerfiles: Properly set up non-root users Previously, the `crux-{llvm,mir}` Docker images were set up to use `root` accounts, and all files that were created in the Docker images were given `root` permissions. This is impractical for running rootless container environments, as noted in #1261. This rewrites the images to set the default users to unprivileges `crux-{llvm,mir}` users. This is surprisingly involved, and it requires a fair bit of refactoring to accomplish: 1. We cannot easily base the `crux-mir` image on the official `rust` image, as the latter has `cargo`, `rustup`, and related tools installed under a `root` account. Instead, we change to an unprivileged user and install these Rust tools using rustup.sh's installer script. 2. Previously, the `crux-llvm` image was supporting Unicode character printing by changing the locale, which requires root access to accomplish. This is overkill, however, as it suffices to simply set the `LANG` and `LC_ALL` environment variables. I've opted for the latter approach, which is much simpler and avoids the need for root access. 3. I needed to reorganize the order of commands in the `base` layers of each image in order to ensure that the relevant files are `chown`ed from the unprivileged user accounts. Fixes #1261. --- .github/Dockerfile-crux-llvm | 117 ++++++++++++++++++----------------- .github/Dockerfile-crux-mir | 115 ++++++++++++++++------------------ 2 files changed, 114 insertions(+), 118 deletions(-) diff --git a/.github/Dockerfile-crux-llvm b/.github/Dockerfile-crux-llvm index d8936966e..85191d9aa 100644 --- a/.github/Dockerfile-crux-llvm +++ b/.github/Dockerfile-crux-llvm @@ -14,83 +14,86 @@ RUN apt-get update && \ # LLVM toolchain clang-${LLVM_VER} llvm-${LLVM_VER}-tools \ # Miscellaneous - locales unzip wget -RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ - locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 + unzip wget -WORKDIR /usr/local/bin +ARG CRUX_BUILD_DIR=/crux-llvm/build +RUN mkdir -p ${CRUX_BUILD_DIR} +ADD crucible ${CRUX_BUILD_DIR}/crucible +ADD crucible-llvm ${CRUX_BUILD_DIR}/crucible-llvm +ADD crucible-symio ${CRUX_BUILD_DIR}/crucible-symio +ADD crux ${CRUX_BUILD_DIR}/crux +ADD crux-llvm ${CRUX_BUILD_DIR}/crux-llvm +ADD dependencies ${CRUX_BUILD_DIR}/dependencies +ADD .github/cabal.project.crux-llvm ${CRUX_BUILD_DIR}/cabal.project +ADD cabal.GHC-9.4.8.config ${CRUX_BUILD_DIR}/cabal.project.freeze +# Workaround until we have a more recent LLVM build available +RUN cp ${CRUX_BUILD_DIR}/crux-llvm/c-src/libcxx-7.1.0.bc ${CRUX_BUILD_DIR}/crux-llvm/c-src/libcxx-${LLVM_VER}.0.0.bc + +RUN useradd -m crux-llvm && chown -R crux-llvm:crux-llvm /crux-llvm +USER crux-llvm +WORKDIR /crux-llvm + +ENV CLANG=clang-${LLVM_VER} \ + LLVM_LINK=llvm-link-${LLVM_VER} \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + +RUN mkdir -p rootfs/usr/local/bin +WORKDIR rootfs/usr/local/bin # The URL here is based on the same logic used to specify BUILD_TARGET_OS and # BUILD_TARGET_ARCH in `.github/workflow/crux-llvm-build.yml`, but specialized # to x86-64 Ubuntu. RUN curl -o solvers.zip -sL "https://github.com/GaloisInc/what4-solvers/releases/download/snapshot-20240212/ubuntu-22.04-X64-bin.zip" RUN unzip solvers.zip && rm solvers.zip && chmod +x * -ENV PATH=/root/ghcup-download/bin:/root/.ghcup/bin:$PATH -RUN mkdir -p /root/ghcup-download/bin && \ - curl -L https://downloads.haskell.org/~ghcup/0.1.17.7/x86_64-linux-ghcup-0.1.17.7 -o /root/ghcup-download/bin/ghcup && \ - chmod +x /root/ghcup-download/bin/ghcup -RUN mkdir -p /root/.ghcup && \ +WORKDIR /crux-llvm +ENV PATH=/crux-llvm/rootfs/usr/local/bin:/home/crux-llvm/.local/bin:/home/crux-llvm/.ghcup/bin:$PATH +RUN mkdir -p /home/crux-llvm/.local/bin && \ + curl -L https://downloads.haskell.org/~ghcup/0.1.17.7/x86_64-linux-ghcup-0.1.17.7 -o /home/crux-llvm/.local/bin/ghcup && \ + chmod +x /home/crux-llvm/.local/bin/ghcup +RUN mkdir -p /home/crux-llvm/.ghcup && \ ghcup --version && \ ghcup install cabal 3.10.3.0 && \ ghcup install ghc 9.4.8 && \ ghcup set ghc 9.4.8 -RUN cabal v2-update - -ARG DIR=/crux-llvm -WORKDIR ${DIR} -RUN mkdir -p ${DIR}/build -ADD crucible ${DIR}/build/crucible -ADD crucible-llvm ${DIR}/build/crucible-llvm -ADD crucible-symio ${DIR}/build/crucible-symio -ADD crux ${DIR}/build/crux -ADD crux-llvm ${DIR}/build/crux-llvm -ADD dependencies ${DIR}/build/dependencies -ADD .github/cabal.project.crux-llvm ${DIR}/build/cabal.project -ADD cabal.GHC-9.4.8.config ${DIR}/build/cabal.project.freeze -# Workaround until we have a more recent LLVM build available -RUN cp $DIR/build/crux-llvm/c-src/libcxx-7.1.0.bc $DIR/build/crux-llvm/c-src/libcxx-${LLVM_VER}.0.0.bc -WORKDIR ${DIR}/build -RUN cabal v2-build --only-dependencies crux-llvm -RUN cabal v2-build crux-llvm -ENV CLANG=clang-${LLVM_VER} -ENV LLVM_LINK=llvm-link-${LLVM_VER} -RUN cabal v2-test crux-llvm -RUN cp `cabal v2-exec which crux-llvm` /usr/local/bin -RUN cp `cabal v2-exec which crux-llvm-svcomp` /usr/local/bin +WORKDIR ${CRUX_BUILD_DIR} +RUN cabal v2-update && \ + cabal v2-build --only-dependencies crux-llvm && \ + cabal v2-build crux-llvm && \ + cabal v2-test crux-llvm && \ + cp `cabal v2-exec which crux-llvm` /crux-llvm/rootfs/usr/local/bin && \ + cp `cabal v2-exec which crux-llvm-svcomp` /crux-llvm/rootfs/usr/local/bin +USER root +RUN chown -R root:root /crux-llvm/rootfs FROM ubuntu:22.04 ARG LLVM_VER -USER root RUN apt-get update && \ apt-get install -y \ - libgmp10 zlib1g clang-${LLVM_VER} llvm-${LLVM_VER}-tools unzip locales - -COPY --from=build /usr/local/bin/* /usr/local/bin/ + libgmp10 zlib1g clang-${LLVM_VER} llvm-${LLVM_VER}-tools unzip -ARG DIR=/crux-llvm -WORKDIR ${DIR} +COPY --from=build /crux-llvm/rootfs / +WORKDIR /crux-llvm ADD crux-llvm/c-src c-src -# Use LLVM 7 bitcode file for libcxx until a more recent LLVM version is available -RUN cp c-src/libcxx-7.1.0.bc c-src/libcxx-${LLVM_VER}.0.0.bc +RUN \ + # Use LLVM 7 bitcode file for libcxx until a more recent LLVM version is available + cp c-src/libcxx-7.1.0.bc c-src/libcxx-${LLVM_VER}.0.0.bc && \ + # (Temporary) fix for + # https://github.com/galoisinc/crucible/issues/887: the libDir default + # is relative to the executable or failing that, the data dir as + # reported by the build process, but neither matches WORKDIR/c-src. + cp -r c-src /usr/local/ -# (Temporary) fix for -# https://github.com/galoisinc/crucible/issues/887: the libDir default -# is relative to the executable or failing that, the data dir as -# reported by the build process, but neither matches WORKDIR/c-src. -RUN cp -r c-src /usr/local/ - -RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ - locale-gen +RUN useradd -m crux-llvm && chown -R crux-llvm:crux-llvm /crux-llvm /home/crux-llvm USER crux-llvm -ENV LD_LIBRARY_PATH=/usr/local/lib -ENV CLANG=clang-${LLVM_VER} -ENV LLVM_LINK=llvm-link-${LLVM_VER} -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 +WORKDIR / + +ENV LD_LIBRARY_PATH=/usr/local/lib \ + CLANG=clang-${LLVM_VER} \ + LLVM_LINK=llvm-link-${LLVM_VER} \ + LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 + ENTRYPOINT ["/usr/local/bin/crux-llvm"] diff --git a/.github/Dockerfile-crux-mir b/.github/Dockerfile-crux-mir index 0eff391c2..073eeb84a 100644 --- a/.github/Dockerfile-crux-mir +++ b/.github/Dockerfile-crux-mir @@ -1,19 +1,11 @@ # If you update this, make sure to also update RUST_TOOLCHAIN in # .github/workflows/crux-mir-build.yml ARG RUST_TOOLCHAIN="nightly-2023-01-23" - -FROM rust:1.46.0 AS mir_json -ARG RUST_TOOLCHAIN - -ADD dependencies/mir-json /mir-json -WORKDIR /mir-json -RUN rustup toolchain install ${RUST_TOOLCHAIN} --force -RUN rustup component add --toolchain ${RUST_TOOLCHAIN} rustc-dev -RUN rustup default ${RUST_TOOLCHAIN} -RUN cargo install --locked +ARG CRUX_BUILD_DIR=/crux-mir/build FROM ubuntu:22.04 AS build ARG RUST_TOOLCHAIN +ARG CRUX_BUILD_DIR RUN apt-get update && \ apt-get install -y \ @@ -24,78 +16,79 @@ RUN apt-get update && \ # Miscellaneous unzip wget -COPY --from=mir_json /usr/local/cargo /usr/local/cargo -COPY --from=mir_json /usr/local/rustup /usr/local/rustup -WORKDIR /usr/local/bin +RUN mkdir -p ${CRUX_BUILD_DIR} +ADD crucible ${CRUX_BUILD_DIR}/crucible +ADD crucible-concurrency ${CRUX_BUILD_DIR}/crucible-concurrency +ADD crucible-mir ${CRUX_BUILD_DIR}/crucible-mir +ADD crucible-syntax ${CRUX_BUILD_DIR}/crucible-syntax +ADD crux ${CRUX_BUILD_DIR}/crux +ADD crux-mir ${CRUX_BUILD_DIR}/crux-mir +ADD dependencies ${CRUX_BUILD_DIR}/dependencies +ADD .github/cabal.project.crux-mir ${CRUX_BUILD_DIR}/cabal.project +ADD cabal.GHC-9.4.8.config ${CRUX_BUILD_DIR}/cabal.project.freeze + +RUN useradd -m crux-mir && chown -R crux-mir:crux-mir /crux-mir +USER crux-mir +WORKDIR /crux-mir + +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + PATH=/crux-mir/rootfs/usr/local/bin:/home/crux-mir/.cargo/bin:/home/crux-mir/.local/bin:/home/crux-mir/.ghcup/bin:$PATH + +WORKDIR ${CRUX_BUILD_DIR}/dependencies/mir-json +RUN curl https://sh.rustup.rs -sSf | bash -s -- -y --profile minimal --default-toolchain ${RUST_TOOLCHAIN} +RUN rustup component add --toolchain ${RUST_TOOLCHAIN} rustc-dev +RUN cargo install --locked + +RUN mkdir -p /crux-mir/rootfs/usr/local/bin +WORKDIR /crux-mir/rootfs/usr/local/bin # The URL here is based on the same logic used to specify BUILD_TARGET_OS and # BUILD_TARGET_ARCH in `.github/workflow/crux-mir-build.yml`, but specialized # to x86-64 Ubuntu. RUN curl -o solvers.zip -sL "https://github.com/GaloisInc/what4-solvers/releases/download/snapshot-20240212/ubuntu-22.04-X64-bin.zip" RUN unzip solvers.zip && rm solvers.zip && chmod +x * -ENV CARGO_HOME=/usr/local/cargo -ENV RUSTUP_HOME=/usr/local/rustup -ENV LD_LIBRARY_PATH=/usr/local/lib:/usr/local/rustup/lib -ENV LANG=C.UTF-8 \ - LC_ALL=C.UTF-8 - -ENV PATH=/root/ghcup-download/bin:/root/.ghcup/bin:$PATH -RUN mkdir -p /root/ghcup-download/bin && \ - curl -L https://downloads.haskell.org/~ghcup/0.1.17.7/x86_64-linux-ghcup-0.1.17.7 -o /root/ghcup-download/bin/ghcup && \ - chmod +x /root/ghcup-download/bin/ghcup -RUN mkdir -p /root/.ghcup && \ +WORKDIR /crux-mir +RUN mkdir -p /home/crux-mir/.local/bin && \ + curl -L https://downloads.haskell.org/~ghcup/0.1.17.7/x86_64-linux-ghcup-0.1.17.7 -o /home/crux-mir/.local/bin/ghcup && \ + chmod +x /home/crux-mir/.local/bin/ghcup +RUN mkdir -p /home/crux-mir/.ghcup && \ ghcup --version && \ ghcup install cabal 3.10.3.0 && \ ghcup install ghc 9.4.8 && \ ghcup set ghc 9.4.8 -RUN cabal v2-update - -ARG DIR=/crux-mir -RUN mkdir -p ${DIR}/build -ADD crucible ${DIR}/build/crucible -ADD crucible-concurrency ${DIR}/build/crucible-concurrency -ADD crucible-mir ${DIR}/build/crucible-mir -ADD crucible-syntax ${DIR}/build/crucible-syntax -ADD crux ${DIR}/build/crux -ADD crux-mir ${DIR}/build/crux-mir -ADD dependencies ${DIR}/build/dependencies -ADD .github/cabal.project.crux-mir ${DIR}/build/cabal.project -ADD cabal.GHC-9.4.8.config ${DIR}/build/cabal.project.freeze -WORKDIR ${DIR}/build -RUN cabal v2-build --only-dependencies crux-mir -RUN cabal v2-build crux-mir -RUN cp `cabal v2-exec which crux-mir` /usr/local/bin -RUN cp /usr/local/cargo/bin/* /usr/local/bin/ -RUN rustup default ${RUST_TOOLCHAIN} -WORKDIR ${DIR}/build/crux-mir +WORKDIR ${CRUX_BUILD_DIR}/crux-mir RUN ./translate_libs.sh -WORKDIR ${DIR}/build -RUN cabal v2-test crux-mir +WORKDIR ${CRUX_BUILD_DIR} +RUN cabal v2-update && \ + cabal v2-build --only-dependencies crux-mir && \ + cabal v2-build crux-mir && \ + cabal v2-test crux-mir && \ + cp `cabal v2-exec which crux-mir` /crux-mir/rootfs/usr/local/bin +USER root +RUN chown -R root:root /crux-mir/rootfs FROM ubuntu:22.04 +ARG CRUX_BUILD_DIR -USER root RUN apt-get update && \ apt-get install -y \ libgmp10 zlib1g libcurl4 \ # A C toolchain (needed to build crates that require a C compiler) clang -ARG DIR=/crux-mir -COPY --from=mir_json /usr/local/cargo /usr/local/cargo -COPY --from=mir_json /usr/local/rustup /usr/local/rustup -COPY --from=build /usr/local/bin/* /usr/local/bin/ -COPY --from=build /crux-mir/build/crux-mir/rlibs /crux-mir/rlibs -RUN mkdir -p ${DIR}/workspace - -WORKDIR ${DIR}/workspace +COPY --from=build /home/crux-mir/.cargo/bin /home/crux-mir/.cargo/bin +COPY --from=build /home/crux-mir/.rustup /home/crux-mir/.rustup +COPY --from=build /crux-mir/rootfs / +COPY --from=build ${CRUX_BUILD_DIR}/crux-mir/rlibs /crux-mir/rlibs +RUN useradd -m crux-mir && chown -R crux-mir:crux-mir /crux-mir /home/crux-mir USER crux-mir -ENV CARGO_HOME=/usr/local/cargo \ - RUSTUP_HOME=/usr/local/rustup \ - CRUX_RUST_LIBRARY_PATH=/crux-mir/rlibs \ - LD_LIBRARY_PATH=/usr/local/lib:/usr/local/rustup/lib \ - LANG=C.UTF-8 \ - LC_ALL=C.UTF-8 +WORKDIR / + +ENV LANG=C.UTF-8 \ + LC_ALL=C.UTF-8 \ + PATH=/home/crux-mir/.cargo/bin:$PATH + ENTRYPOINT ["/usr/local/bin/cargo", "crux-test"]