1#!/usr/bin/env bash
2# Copyright 2019 The Hafnium Authors.
3#
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file or at
6# https://opensource.org/licenses/BSD-3-Clause.
7
8set -euo pipefail
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11ROOT_DIR="$(dirname ${SCRIPT_DIR})"
12
13source "${SCRIPT_DIR}/docker/common.inc"
14
15if [ "${HAFNIUM_HERMETIC_BUILD:-}" == "inside" ]
16then
17	echo "ERROR: Invoked $0 recursively" 1>&2
18	exit 1
19fi
20
21# Set up a temp directory and register a cleanup function on exit.
22TMP_DIR="$(mktemp -d)"
23function cleanup() {
24	rm -rf "${TMP_DIR}"
25}
26trap cleanup EXIT
27
28# Build local image and write its hash to a temporary file.
29IID_FILE="${TMP_DIR}/imgid.txt"
30"${DOCKER}" build \
31	--build-arg LOCAL_UID="$(id -u)" \
32	--build-arg LOCAL_GID="$(id -g)" \
33	--iidfile="${IID_FILE}" \
34	-f "${SCRIPT_DIR}/docker/Dockerfile.local" \
35	"${SCRIPT_DIR}/docker"
36IMAGE_ID="$(cat ${IID_FILE})"
37
38# Parse command line arguments
39INTERACTIVE=false
40ALLOW_PTRACE=false
41while true
42do
43	case "${1:-}" in
44	-i)
45		INTERACTIVE=true
46		shift
47		;;
48	-p)
49		ALLOW_PTRACE=true
50		shift
51		;;
52	-*)
53		echo "ERROR: Unknown command line flag: $1" 1>&2
54		echo "Usage: $0 [-i] [-p] <command>"
55		exit 1
56		;;
57	*)
58		break
59		;;
60	esac
61done
62
63ARGS=()
64# Run with a pseduo-TTY for nicer logging.
65ARGS+=(-t)
66# Run interactive if this script was invoked with '-i'.
67if [ "${INTERACTIVE}" == "true" ]
68then
69	ARGS+=(-i)
70fi
71# Allow ptrace() syscall if invoked with '-p'.
72if [ "${ALLOW_PTRACE}" == "true" ]
73then
74	echo "WARNING: Docker seccomp profile is disabled!" 1>&2
75	ARGS+=(--cap-add=SYS_PTRACE --security-opt seccomp=unconfined)
76fi
77# Propagate "HAFNIUM_*" environment variables.
78# Note: Cannot use `env | while` because the loop would run inside a child
79# process and would not have any effect on variables in the parent.
80while read -r ENV_LINE
81do
82	VAR_NAME="$(echo ${ENV_LINE} | cut -d= -f1)"
83	case "${VAR_NAME}" in
84	HAFNIUM_HERMETIC_BUILD)
85		# Skip this one. It will be overridden below.
86		;;
87	HAFNIUM_*)
88		ARGS+=(-e "${ENV_LINE}")
89		;;
90	esac
91done <<< "$(env)"
92# Set environment variable informing the build that we are running inside
93# a container.
94ARGS+=(-e HAFNIUM_HERMETIC_BUILD=inside)
95# Bind-mount the Hafnium root directory. We mount it at the same absolute
96# location so that all paths match across the host and guest.
97ARGS+=(-v "${ROOT_DIR}":"${ROOT_DIR}")
98# Make all files outside of the Hafnium directory read-only to ensure that all
99# generated files are written there.
100ARGS+=(--read-only)
101# Mount a writable /tmp folder. Required by LLVM/Clang for intermediate files.
102ARGS+=(--tmpfs /tmp)
103# Set working directory.
104ARGS+=(-w "${ROOT_DIR}")
105
106echo "Running in container: $*" 1>&2
107${DOCKER} run \
108	${ARGS[@]} \
109	"${IMAGE_ID}" \
110	/bin/bash -c "$*"
111