diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..339eaaa --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,50 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Set up dependencies + run: | + sudo apt-get update + sudo apt-get install -y make + + sudo apt install -y skopeo + + sudo apt install -y curl tar + curl -L https://github.com/opencontainers/umoci/releases/download/v0.5.1/umoci.linux.amd64 -o umoci + chmod +x umoci + sudo mv umoci /usr/local/bin/umoci + + - name: Create cgroup v2 hierarchy + run: | + sudo systemctl enable user@$(id -u).service + sudo echo "+cpu +memory +pids +io +cpuset" | sudo tee /sys/fs/cgroup/user.slice/cgroup.subtree_control + sudo echo "+cpu +memory +pids +io +cpuset" | sudo tee /sys/fs/cgroup/user.slice/user-$(id -u).slice/cgroup.subtree_control + sudo echo "+cpu +memory +pids +io +cpuset" | sudo tee /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.subtree_control + export LIME_CGROUP_ROOT=/sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/lime + mkdir -p $LIME_CGROUP_ROOT + ls -la /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/lime + echo "+cpu +memory +pids +io +cpuset" > $LIME_CGROUP_ROOT/cgroup.subtree_control + echo "LIME_CGROUP_ROOT=$LIME_CGROUP_ROOT" >> $GITHUB_ENV + + - name: Build Lime + run: | + mkdir -p build + make -j$(nproc) + + - name: Run tests + run: | + sudo sysctl kernel.unprivileged_userns_clone=1 + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + ./scripts/setup_rootfs.sh + systemd-run --user --scope ./scripts/run_lime.sh basic.cpp diff --git a/.gitignore b/.gitignore index d3e6f09..8de15fc 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,9 @@ Thumbs.db # Build directories /build/ +# Images +/images/ + # IDE .vscode/ .idea/ diff --git a/scripts/run_lime.sh b/scripts/run_lime.sh index 0495fa6..0024f21 100755 --- a/scripts/run_lime.sh +++ b/scripts/run_lime.sh @@ -30,10 +30,10 @@ LIME_MAX_PROCESSES="10" LIME_OUTPUT_LIMIT_BYTES="8388608" LIME_MAX_OPEN_FILES="16" LIME_STACK_LIMIT_BYTES="8388608" -LIME_USE_CPUS="4" +LIME_USE_CPUS="0" LIME_USE_MEMS="0" LIME_STDIN="" -LIME_ROOTFS_PATH="/var/castletown/images/gcc-15-bookworm" +LIME_ROOTFS_PATH="images/gcc-15-bookworm" LIME_BIND_MOUNTS_JSON="[\"/tmp/lime_test_compile_input:/tmp/input:ro\", \"/tmp/lime_test_exec_input:/tmp/output\"]" LIME_USE_OVERLAYFS="true" diff --git a/scripts/setup_rootfs.sh b/scripts/setup_rootfs.sh new file mode 100755 index 0000000..8327587 --- /dev/null +++ b/scripts/setup_rootfs.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +set -euo pipefail + +IMAGE_REF=${PULL_IMAGE_REF:-"gcc:15-bookworm"} +IMAGE_NAME=${PULL_IMAGE_NAME:-"gcc-15-bookworm"} +IMAGES_DIR=${JUDGE_IMAGES_DIR:-${IMAGES_DIR:-"./images"}} +TMP_DIR=${TMP_DIR:-"/tmp/lime-setup-rootfs"} + +mkdir -p "${IMAGES_DIR}" +mkdir -p "${TMP_DIR}" + +if [[ -d "${IMAGES_DIR}/${IMAGE_NAME}" ]]; then + echo "[rootfs] ${IMAGES_DIR}/${IMAGE_NAME} already exists, nothing to do" + exit 0 +fi + +if ! command -v skopeo >/dev/null 2>&1; then + echo "[rootfs] skopeo is required but not installed" >&2 + exit 1 +fi + +if ! command -v umoci >/dev/null 2>&1; then + echo "[rootfs] umoci is required but not installed" >&2 + exit 1 +fi + +oci_dir=$(mktemp -d -p "${TMP_DIR}" lime-oci-XXXXXX) +rootfs_dir=$(mktemp -d -p "${TMP_DIR}" lime-rootfs-XXXXXX) +trap 'rm -rf "${oci_dir}" "${rootfs_dir}"' EXIT + +echo "[rootfs] downloading ${IMAGE_REF}" +skopeo copy "docker://${IMAGE_REF}" "oci:${oci_dir}:${IMAGE_NAME}" + +echo "[rootfs] unpacking image" +umoci raw unpack --rootless \ + --image "${oci_dir}:${IMAGE_NAME}" \ + "${rootfs_dir}" + +source_dir="${rootfs_dir}/rootfs" +if [[ ! -d "${source_dir}" ]]; then + # umoci versions prior to 0.5 place the rootfs directly at the destination + source_dir="${rootfs_dir}" +fi + +if [[ ! -d "${source_dir}" ]]; then + echo "[rootfs] unpack failed: ${source_dir} not found" >&2 + exit 1 +fi + +mkdir -p "${IMAGES_DIR}/${IMAGE_NAME}" +cp -r "${source_dir}/." "${IMAGES_DIR}/${IMAGE_NAME}/" +mkdir -p "${IMAGES_DIR}/${IMAGE_NAME}/box" + +echo "[rootfs] prepared ${IMAGES_DIR}/${IMAGE_NAME}" + +exit 0 diff --git a/src/run.c b/src/run.c index 2b07613..0379e52 100644 --- a/src/run.c +++ b/src/run.c @@ -812,9 +812,10 @@ static int child_fn(void *arg) { ExecRequest *cfg = args->cfg; // set mount propagation to private - if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) { - fprintf(stderr, "Failed to make / private: %m\n"); - return -1; + if(mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) { + perror("mount private"); + write_byte(sync_fd, 'X'); + _exit(1); } // wait for parent to setup uid/gid maps