dev_container: Use host UID & GID for user in container

Container shell now defaults to user `crosvmdev` which will have
same UID & GID as outside user. VS Code Remote Containers extension
has the same behavior when loading config from devcontainer.json.

TEST=all tests pass in container, new files in container have same
permission as files created outside.
FIXED=b:239476013

Change-Id: Ib3c696509e9ea45edd5f02ff025d9477576ec765
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3814094
Auto-Submit: Zihan Chen <zihanchen@google.com>
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Tested-by: Zihan Chen <zihanchen@google.com>
Commit-Queue: Dennis Kempin <denniskempin@google.com>
This commit is contained in:
Zihan Chen 2022-08-05 13:41:33 -07:00 committed by crosvm LUCI
parent 53298c039d
commit 483345c4c0
7 changed files with 90 additions and 27 deletions

View file

@ -1,5 +1,5 @@
{ {
"image": "gcr.io/crosvm-infra/crosvm_dev:r0015", "image": "gcr.io/crosvm-infra/crosvm_dev:r0019",
"extensions": [ "extensions": [
"rust-lang.rust-analyzer", "rust-lang.rust-analyzer",
"bungcip.better-toml", "bungcip.better-toml",
@ -16,5 +16,9 @@
"--device=/dev/vhost-net", "--device=/dev/vhost-net",
"--device=/dev/vhost-vsock", "--device=/dev/vhost-vsock",
"--mount=type=tmpfs,destination=/tmp", "--mount=type=tmpfs,destination=/tmp",
] "--mount=type=tmpfs,destination=/var/empty",
],
"containerUser": "crosvmdev",
"updateContentCommand": "sudo chown -R --reference=/workspaces/crosvm /home/crosvmdev",
"postCreateCommand": "sudo chmod 666 /dev/kvm",
} }

View file

@ -17,7 +17,8 @@ fn prepare_disk_img() -> NamedTempFile {
disk.as_file_mut().set_len(1024 * 1024).unwrap(); disk.as_file_mut().set_len(1024 * 1024).unwrap();
// TODO(b/243127910): Use `mkfs.ext4 -d` to include test data. // TODO(b/243127910): Use `mkfs.ext4 -d` to include test data.
Command::new("mkfs.ext4") Command::new("sudo")
.arg("mkfs.ext4")
.arg(disk.path().to_str().unwrap()) .arg(disk.path().to_str().unwrap())
.output() .output()
.expect("failed to execute process"); .expect("failed to execute process");

View file

@ -50,6 +50,8 @@ DOCKER_ARGS = [
"--mount type=tmpfs,destination=/tmp", "--mount type=tmpfs,destination=/tmp",
# For plugin process jail # For plugin process jail
"--mount type=tmpfs,destination=/var/empty", "--mount type=tmpfs,destination=/var/empty",
f"--env OUTSIDE_UID={os.getuid()}",
f"--env OUTSIDE_GID={os.getgid()}",
f"gcr.io/crosvm-infra/crosvm_dev:{IMAGE_VERSION}", f"gcr.io/crosvm-infra/crosvm_dev:{IMAGE_VERSION}",
] ]
@ -165,14 +167,18 @@ def main(
tty_args = ["--interactive", "--tty"] tty_args = ["--interactive", "--tty"]
# Start an interactive shell by default # Start an interactive shell by default
if not command:
command = ("/bin/bash",)
quoted_cmd = list(map(quoted, command))
if hermetic: if hermetic:
# cmd is passed to entrypoint
quoted_cmd = list(map(quoted, command))
docker(f"run --rm", *tty_args, *docker_args, *quoted_cmd).fg() docker(f"run --rm", *tty_args, *docker_args, *quoted_cmd).fg()
else: else:
# cmd is executed directly
cid = ensure_container_is_alive(docker, docker_args) cid = ensure_container_is_alive(docker, docker_args)
if not command:
command = ("/tools/entrypoint.sh",)
else:
command = ("/tools/entrypoint.sh",) + tuple(command)
quoted_cmd = list(map(quoted, command))
docker("exec", *tty_args, cid, *quoted_cmd).fg() docker("exec", *tty_args, cid, *quoted_cmd).fg()

View file

@ -5,45 +5,56 @@ ARG RUST_VERSION
FROM docker.io/rust:${RUST_VERSION}-slim-bullseye FROM docker.io/rust:${RUST_VERSION}-slim-bullseye
# Use a dedicated target directory so we do not write into the source directory. # Use a dedicated target directory so we do not write into the source directory.
RUN mkdir -p /scratch/cargo_target RUN mkdir -p /scratch/cargo_target \
ENV CARGO_TARGET_DIR=/scratch/cargo_target && mkdir /cache
# Prevent the container from writing root-owned __pycache__ files into the src. # Prevent the container from writing __pycache__ files into the src.
ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONDONTWRITEBYTECODE=1
ENV CARGO_TARGET_DIR=/scratch/cargo_target
# Add foreign architectures for cross-compilation. # Add foreign architectures for cross-compilation.
RUN dpkg --add-architecture arm64 \ RUN dpkg --add-architecture arm64 \
&& dpkg --add-architecture armhf && dpkg --add-architecture armhf
# Install dependencies for native builds. # Install dependencies.
COPY tools/install-deps /tools/ COPY tools/install-deps tools/install-aarch64-deps tools/install-armhf-deps tools/install-docs-deps /tools/
COPY tools/install-docs-deps /tools/ RUN chmod 755 /tools/install-deps /tools/install-aarch64-deps /tools/install-armhf-deps /tools/install-docs-deps \
RUN apt-get update \ && apt update \
&& apt-get install --yes sudo \ && apt install --yes sudo \
&& /tools/install-deps \ && /tools/install-deps \
&& /tools/install-aarch64-deps \
&& /tools/install-armhf-deps \
&& /tools/install-docs-deps \
# Clear apt cache to save space in layer. # Clear apt cache to save space in layer.
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
# Delete build artifacts from 'cargo install' to save space in layer. # Delete build artifacts from 'cargo install' to save space in layer.
&& rm -rf /scratch/cargo_target/* && rm -rf /scratch/cargo_target/*
# Add a new password-less sudoer user crosvmdev
RUN useradd -ms /bin/bash crosvmdev \
&& usermod -aG sudo crosvmdev \
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
# Pass rust envs from rust toolchain image when sudo into new user
&& echo 'Defaults env_keep += "RUSTUP_HOME CARGO_HOME RUST_VERSION CARGO_TARGET_DIR"' >> /etc/sudoers \
# Allow dependencies and build files to be used and overwritten by user
&& chmod -R 777 /scratch /cache
# Following operations will be run as crosvmdev to ensure correct permission.
USER crosvmdev
# Prepare path to rust toolchain for crosvmdev
RUN echo 'export PATH=/cache/cargo_home/bin:/usr/local/cargo/bin:$PATH' >> /home/crosvmdev/.profile
# Prepare wine64 # Prepare wine64
RUN ln -sf /usr/bin/wine64-stable /usr/bin/wine64 \ RUN sudo ln -sf /usr/bin/wine64-stable /usr/bin/wine64 \
&& wine64 wineboot && wine64 wineboot
# Install cross-compilation dependencies.
COPY tools/install-aarch64-deps tools/install-armhf-deps /tools/
RUN apt-get update \
&& /tools/install-aarch64-deps \
&& /tools/install-armhf-deps \
# Clear apt cache to save space in layer.
&& rm -rf /var/lib/apt/lists/*
# Prebuild aarch64 VM image for faster startup. # Prebuild aarch64 VM image for faster startup.
COPY tools/aarch64vm /tools/ COPY tools/aarch64vm /tools/
COPY /tools/impl/testvm.py /tools/impl/ COPY /tools/impl/testvm.py /tools/impl/
COPY /tools/impl/testvm/version /tools/impl/testvm/ COPY /tools/impl/testvm/version /tools/impl/testvm/
RUN /tools/aarch64vm build RUN sudo chmod 755 /tools/aarch64vm /tools/impl/testvm.py \
&& /tools/aarch64vm build
# Cache CARGO_HOME between container runs in CI. # Cache CARGO_HOME between container runs in CI.
VOLUME /cache VOLUME /cache
@ -51,3 +62,9 @@ ENV CARGO_HOME=/cache/cargo_home
VOLUME /workspace VOLUME /workspace
WORKDIR /workspace WORKDIR /workspace
# Switch back to root to avoid usermod crosvmdev as crosvmdev
USER root
COPY tools/impl/dev_container/entrypoint.sh tools/impl/dev_container/setup-user.sh /tools/
RUN chmod 755 /tools/entrypoint.sh /tools/setup-user.sh
ENTRYPOINT ["/tools/entrypoint.sh"]

View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Copyright 2022 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Ensure there's only 1 instance of setup-user.sh running
flock /tmp/entrypoint_lock /tools/setup-user.sh
# Give KVM device correct permission
chmod 666 /dev/kvm
# Run provided command or interactive shell
if [[ $# -eq 0 ]]; then
sudo -u crosvmdev /bin/bash -l
else
sudo -u crosvmdev /bin/bash -l -c "$*"
fi

View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Copyright 2022 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
if [[ $OUTSIDE_GID != $(sudo -u crosvmdev id -g) ]]; then
groupmod -g "$OUTSIDE_GID" crosvmdev
chgrp -R crosvmdev /home/crosvmdev
fi
if [[ $OUTSIDE_UID != $(sudo -u crosvmdev id -u) ]]; then
usermod -u "$OUTSIDE_UID" crosvmdev
fi
# Transitional section to fix CI's cache permission
chmod -R 777 /cache
if [[ -d /workspace/infra/.recipe_deps ]]; then
chmod -R 777 /workspace/infra/.recipe_deps
fi

View file

@ -1 +1 @@
r0016 r0019