Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile.builder
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ RUN apt-get update \

ARG REPO_ROOT

ARG UID=1000
RUN useradd -u ${UID} builder

COPY cmake /${REPO_ROOT}/cmake
COPY scripts /${REPO_ROOT}/scripts
COPY config /${REPO_ROOT}
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ Then build the toolchain by running

The build artifact is `./output/llvm-pauth.squashfs` file.

The build scripts try to detect the UID of the real user running `./build.sh`
in case this script is executed with `sudo` to make the contents of `./output`
and `./ccache` directories writable without `sudo` by the host user. This is
especially useful to prevent the `host-build` performed with the same `./ccache`
directory from silently falling back to non-cached build.

# Using the toolchain

Mount the produced SquashFS image at `/opt/llvm-pauth`:
Expand Down
26 changes: 26 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,36 @@ build_in_docker() {
check_repo_sha "$ROOT/src/llvm" "$LLVM_SHA"
check_repo_sha "$ROOT/src/musl" "$MUSL_SHA"

# Try creating a non-privileged user inside the container with the same UID
# as the UID of the real user to ensure ./ccache and ./output are writable
# without sudo on the host - this is useful to make sure ccache does not
# silently fall back to non-cached rebuilds in the 'host-build' mode of build.sh.
local UID
if [ "x$SUDO_USER" != "x" ]; then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do we need to manually set this environment variable in the config file if we with to achieve the desired effect? If yes, could you please add a corresponding entry + short description to the config file + mention this variable in README?

Or is it some well-known automatically set environment variable? If yes, could you please clarify who is setting it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUDO_USER is normally set by sudo itself:

Set to the login name of the user who invoked sudo.

Added a comment in 03a97e7, thanks.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, does this imply that one might want to run build.sh under sudo for some reasons? I'm just not sure if it's a good idea... Maybe I'm missing smth though.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, does this imply that one might want to run build.sh under sudo for some reasons?

Yes, locally I usually run docker using sudo - maybe this is against the best practices, but I'm not sure. I could drop the part with SUDO_USER at all, as this seems to be the trickiest part of the PR. On the other hand, I'm not sure which are the best practices for other container engines, such as daemon-less Podman.

Frankly speaking, I'm a bit worried about this PR in general from the security perspective as it deals with going from non-privileged user to privileged one and vice versa. On the other hand, if the current user is able to launch rootful Ubuntu docker container and mount own directories as volumes into it, then exactly the same actions can be performed manually :)

# SUDO_USER is set by `sudo` ("login name of the user who invoked sudo").
UID="$(id -u "$SUDO_USER")"
else
UID="$(id -u)"
fi

local rw_dir
for rw_dir in "$ROOT/output" "$ROOT/ccache" "$ROOT/tmp"; do
# Make sure $rw_dir is not created by `docker run`, otherwise it may
# end up being only writable by the root user.
mkdir -p "$rw_dir"
# Ignore "Permission denied" errors if our non-privileged user is allowed
# to execute `docker` without sudo - in that case `./build.sh build` does
# not otherwise require elevating its privileges explicitly, but `chown`
# may fail. Assuming that the $rw_dir was created by the above `mkdir`
# command, the ownership is already correct, thus ignore failed `chown`.
chown $UID:$UID "$rw_dir" || true
done

$DOCKER_CMD build \
-t "$DOCKER_IMAGE_NAME" \
-f Dockerfile.builder \
--build-arg REPO_ROOT="$REPO_ROOT" \
--build-arg UID="$UID" \
"$ROOT"
$DOCKER_CMD run -ti --rm \
--volume "$ROOT/output:$OUTPUT_DIR:rw" \
Expand Down
4 changes: 4 additions & 0 deletions scripts/build-in-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
set -xe
cd "$(dirname "$0")"

if [ "$1" != "no-switch-user" ]; then
exec su builder -c "$0 no-switch-user"
fi

# This script is an entry point inside the Docker container.
# Its location is expected to be $REPO_ROOT/scripts/build-in-docker.sh.

Expand Down