From 8ea702f3f853c4c28a2885dafdcae2e737c0a49b Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 19 Aug 2024 18:06:23 +0000 Subject: [PATCH] make.sh: Fix build with kernels < 6.0.0 unshare(8) seems to fail with kernels older than 6.0.0 when mounting the /proc filesystem in the inner namespace. This seems to be an bug where unshare does not even try to mount the /proc filesystem but tries to make its mount propagation private. This is now solved in that way that we will use unshare on newer kernels but will fall back on manually mounting the /proc filesystem once we have entered the chroot environment. Signed-off-by: Michael Tremer --- make.sh | 85 +++++++++++++++++++++++++++++++++++++++++++++--- tools/execute.sh | 5 +++ 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/make.sh b/make.sh index 8e0154107f..f2738eec4b 100755 --- a/make.sh +++ b/make.sh @@ -42,6 +42,7 @@ TOOLCHAINVER=20240521 ############################################################################### HOST_ARCH="${HOSTTYPE}" +HOST_KERNEL="$(uname -r)" LC_ALL=POSIX PS1='\u:\w$ ' @@ -290,6 +291,76 @@ __timer_event() { return 0 } +version_compare() { + local v1="${1}" + local op="${2}" + local v2="${3}" + + # Split both versions by . + v1=( ${v1//./ } ) + v2=( ${v2//./ } ) + + # Run for as long as both versions have not been fully processed + while [ "${#v1[@]}" -gt 0 ] && [ "${#v2[@]}" -gt 0 ]; do + # Fetch the first element from each version + local f1="${v1[@]:0:1}" + local f2="${v2[@]:0:1}" + + # Shift the array + v1=( ${v1[@]:1} ) + v2=( ${v2[@]:1} ) + + local n1 + local n2 + + # Split off any numeric parts + if [[ ${f1} =~ ^([0-9]+) ]]; then + n1="${BASH_REMATCH[1]}" + fi + + if [[ ${f2} =~ ^([0-9]+) ]]; then + n2="${BASH_REMATCH[1]}" + fi + + # Remove the numeric parts from each field + f1="${f1#${n1}}" + f2="${f2#${n2}}" + + # Check the numeric parts first + if [ -n "${n1}" ] && [ -n "${n2}" ]; then + case "${op}" in + ge) + if [ "${n1}" -ge "${n2}" ]; then + return 1 + fi + ;; + esac + + # If we only have a numeric part in the first version... + elif [ -n "${n1}" ]; then + case "${op}" in + ge) + return 1 + ;; + esac + + # If we only have a numeric part in the second version... + elif [ -n "${n2}" ]; then + case "${op}" in + ge) + return 0 + ;; + esac + fi + + # I don't know how to handle the non-numeric part here, and we should not need it + # as we are only using this for kernel versions which should all lead with numbers. + done + + # Don't know + return 0 +} + exiterror() { # Dump logfile if [ -n "${LOGFILE}" ] && [ -e "${LOGFILE}" ]; then @@ -662,13 +733,19 @@ execute() { # Create a new UTS namespace "--uts" - # Mount /proc so that the build environment does not see - # any foreign processes. - "--mount-proc=${BUILD_DIR}/proc" - # If unshare is asked to terminate, terminate all child processes "--kill-child" ) + + # Mount /proc so that the build environment does not see + # any foreign processes. + # This does not work on kernels < 6.0.0, and we will mount /proc + # in the execute.sh script instead. + if version_compare "${HOST_KERNEL}" ge "6.0.0"; then + unshare+=( + "--mount-proc=${BUILD_DIR}/proc" + ) + fi fi while [ $# -gt 0 ]; do diff --git a/tools/execute.sh b/tools/execute.sh index b3bf42f223..7a5b218b43 100755 --- a/tools/execute.sh +++ b/tools/execute.sh @@ -22,6 +22,11 @@ # This is a helper script that is called after we have created the new # namespaces to perform further setup. This will be executed on the host. +# Mount /proc if it has not been mounted, yet +if ! mountpoint /proc; then + mount -t procfs none /proc -o nosuid,noexec,nodev +fi + # Bring up the loopback interface ip link set lo up &>/dev/null -- 2.39.5