Fix multiple mount issue 98/273598/21
authorwang biao <biao716.wang@samsung.com>
Fri, 8 Apr 2022 08:57:19 +0000 (16:57 +0800)
committerwang biao <biao716.wang@samsung.com>
Wed, 20 Apr 2022 09:35:04 +0000 (17:35 +0800)
Change-Id: I6c5fa606cc7e706a461a7df8a9907b1a6de1c51f
Signed-off-by: wang biao <biao716.wang@samsung.com>
common_functions
init_buildsystem
initvm.c

index f0084f8..54a1573 100755 (executable)
@@ -88,20 +88,27 @@ check_exit() {
     fi
 }
 
-check_use_emulator() {
-    INITVM_NAME=
-    # check if the extended host arch contains the build arch
+check_native_arch() {
+    local arch="$1"
     local old_build_arch="$BUILD_ARCH"
-    local arch="${BUILD_ARCH%%:*}"
     BUILD_ARCH="$BUILD_HOST_ARCH"
     extend_build_arch
     BUILD_ARCH=":$BUILD_ARCH:"
     if test "$BUILD_ARCH" != "${BUILD_ARCH/:$arch:/}" ; then
-       # native supported arch, no emulator
        BUILD_ARCH="$old_build_arch"
-       return 1
+       return 0
     fi
     BUILD_ARCH="$old_build_arch"
+    return 1
+}
+
+check_use_emulator() {
+    INITVM_NAME=
+    # check if the extended host arch contains the build arch
+    if check_native_arch "${BUILD_ARCH%%:*}" ; then
+       # native supported arch, no emulator needed
+       return 1
+    fi
 
     # to run the qemu initialization in the vm, we need to
     # register it with a static program or shell script
@@ -158,4 +165,32 @@ buildroot_umount() {
         LOOP_CNT=$((LOOP_CNT+1))
     done
 }
+# rm that makes sure the file is gone
+buildroot_rm() {
+    rm -rf "$BUILD_ROOT/$1"
+    test -e "$BUILD_ROOT/$1" && cleanup_and_exit 1 "could not remove $BUILD_ROOT/$1"
+}
+
+assert_dirs() {
+    local d rl
+    if test -z "$1" ; then
+       set usr sbin usr/bin usr/sbin etc .build .build.oldpackages .init_b_cache .init_b_cache/scripts .init_b_cache/rpms .preinstall_image proc proc/sys proc/sys/fs proc/sys/fs/binfmt_misc sys dev dev/pts dev/shm mnt
+    fi
+    for d in "$@" ; do
+       if test -L "$BUILD_ROOT/$d" ; then
+           rl="$(readlink "$BUILD_ROOT/$d")"
+           test "$d" = sbin -a "x$rl" = "xusr/sbin" && continue
+           test "$d" = sbin -a "x$rl" = "xusr/bin" && continue
+           test "$d" = usr/sbin -a "x$rl" = "xbin" && continue
+           cleanup_and_exit 1 "$d: illegal symlink to $rl"
+       else
+           test -e "$BUILD_ROOT/$d" -a ! -d "$BUILD_ROOT/$d" && cleanup_and_exit 1 "$d: not a directory"
+       fi
+    done
+}
+
+assert_dir_path() {
+    test "$1" != "${1%/*}" && assert_dir_path "${1%/*}"
+    assert_dirs "$1"
+}
 
index 30f4132..6876514 100755 (executable)
@@ -152,45 +152,60 @@ TMPFILE="$BUILD_ROOT"/tmpfile
 #
 # needed functions
 #
-
-cleanup_and_exit() {
-    trap EXIT
-    test "$BUILD_ROOT" = / -a -n "$browner" && chown "$browner" "$BUILD_ROOT"
-    # umount so init_buildsystem can be used standalone
-# XXX: use stat -f /dev/pts/ -c %T  to check whether it's mounted and not suppress errors then?
-    buildroot_umount "/proc/sys/fs/binfmt_misc"
-    buildroot_umount "/proc"
-    buildroot_umount "/sys"
-    buildroot_umount "/dev/pts"
-    buildroot_umount "/dev/shm"
-    buildroot_umount "/mnt"
-    exit ${1:-0}
+mount_stuff() {
+    if test "$UID" = 0 -a -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
+       mount -n -tproc none "$BUILD_ROOT/proc"
+       test -e "$BUILD_ROOT/proc/self" || cleanup_and_exit 1 "Could not mount /proc, is this a container with missing capabilities?"
+       mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT/dev/pts"
+    fi
 }
 
-clean_build_root() {
-    if test -n "$BUILD_ROOT" ; then
+umount_stuff() {
+    if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
        buildroot_umount "/proc/sys/fs/binfmt_misc"
        buildroot_umount "/proc"
        buildroot_umount "/sys"
        buildroot_umount "/dev/pts"
        buildroot_umount "/dev/shm"
        buildroot_umount "/mnt"
+    fi
+}
+
+cleanup_and_exit() {
+    trap EXIT
+    test -z "$1" && set 0
+    if test -n "$2" ; then
+       if test "$1" -ne 0 ; then
+           echo "$2" >&2
+       else
+           echo "$2"
+       fi
+    fi
+    test "$BUILD_ROOT" = / -a -n "$browner" && chown "$browner" "$BUILD_ROOT"
+    # umount so init_buildsystem can be used standalone
+    umount_stuff
+    # never report a fatal error when the job got killed from outside
+    test "$1" = 4 -a -e "$BUILD_ROOT/exit" && exit 1
+    exit $1
+}
+
+clean_build_root() {
+    if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
+       umount_stuff
        rm -rf -- "$BUILD_ROOT"/* 2> /dev/null || true
-       chattr -a -A -i -R -- "$BUILD_ROOT" 2> /dev/null || true
+       chattr -a -A -i -R -- "$BUILD_ROOT" 2> /dev/null || true    # does not follow symlinks
        rm -rf -- "$BUILD_ROOT"/*
        rm -rf -- "$BUILD_ROOT/.build"
+       rm -rf -- "$BUILD_ROOT"/.build.console.*
+       rm -rf -- "$BUILD_ROOT"/.build.hostarch.*
        rm -rf -- "$BUILD_ROOT"/.build.kernel.*
        rm -rf -- "$BUILD_ROOT"/.build.initrd.*
+       rm -rf -- "$BUILD_ROOT"/.build.sysroot
        rm -rf -- "$BUILD_ROOT/.root"
        rm -rf -- "$BUILD_ROOT/.init_b_cache"
+       test -L "$BUILD_ROOT/.preinstall_image" && rm -f -- "$BUILD_ROOT/.preinstall_image"
        rm -rf -- "$BUILD_ROOT"/.preinstall_image/*
        rm -rf -- "$BUILD_ROOT"/.preinstallimage*
-       mkdir -p "$BUILD_ROOT/proc"
-       mkdir -p "$BUILD_ROOT/dev/pts"
-       if test "$UID" = 0 ; then
-           mount -n -tproc none "$BUILD_ROOT/proc"
-           mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT/dev/pts"
-       fi
     fi
 }
 
@@ -281,7 +296,7 @@ create_devs() {
     done << DEVLIST
        mknod null    666 c 1 3
        mknod zero    666 c 1 5
-       mknod full    622 c 1 7
+       mknod full    666 c 1 7
        mknod random  666 c 1 8
        mknod urandom 644 c 1 9
        mknod tty     666 c 5 0
@@ -572,10 +587,7 @@ fi
 if test -e "$BUILD_IS_RUNNING" ; then
     echo "It seems that there was an incomplete setup of $BUILD_ROOT."
     echo "To be sure, we will build it again completely..."
-    umount -n "$BUILD_ROOT"/proc/sys/fs/binfmt_misc 2> /dev/null || true
-    umount -n "$BUILD_ROOT"/proc 2> /dev/null
-    umount -n "$BUILD_ROOT"/dev/pts 2> /dev/null
-    umount -n "$BUILD_ROOT"/mnt 2> /dev/null
+    umount_stuff
     echo "Your build system is broken!! Shall I execute"
     echo
     echo "    rm -rf -- $BUILD_ROOT/*"
@@ -595,11 +607,21 @@ if test -e "$BUILD_IS_RUNNING" ; then
     esac
 fi
 
+# check for surprises
+if test -z "$CLEAN_BUILD" -a -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / ; then
+    assert_dirs
+fi
+
+# umount stuff if mounted
+if test -n "$BUILD_ROOT" -a "$BUILD_ROOT" != / -a -e "$BUILD_ROOT/proc/self" ; then
+    umount_stuff
+fi
+
 #
-# store that we start to build system
+# store that we start to build the system
 #
-mkdir -p "$BUILD_ROOT"
-mkdir -p "$BUILD_ROOT"/.build
+mkdir -p -- "$BUILD_ROOT" "$BUILD_ROOT/.build" "$BUILD_ROOT/proc" "$BUILD_ROOT/sys" "$BUILD_ROOT/dev/pts" || cleanup_and_exit 4
+
 touch $BUILD_IS_RUNNING
 
 if test -n "$PREPARE_VM" ; then
@@ -607,14 +629,8 @@ if test -n "$PREPARE_VM" ; then
 fi
 
 if test -e "$BUILD_ROOT"/.build/init_buildsystem.data ; then
-    # vm continuation
+    # vm continuation, read old config
     . "$BUILD_ROOT"/.build/init_buildsystem.data
-    if ! test -e "$BUILD_ROOT"/.init_b_cache/preinstall_finished ; then
-       # finish preinstall
-       run_pkg_scripts
-       pkg_initdb
-       touch "$BUILD_ROOT"/.init_b_cache/preinstall_finished
-    fi
 else
     #
     # now make sure that all the packages are installed.
@@ -661,7 +677,7 @@ else
     # register the QEMU emulator if needed
     # (we do not need this for the prepare step, as we do not run scripts in this case)
     #
-       copy_qemu
+    copy_qemu
     if test -z "$PREPARE_VM" ; then
        if check_use_emulator ; then
            echo "registering binfmt handlers for cross build"
@@ -884,6 +900,7 @@ if test ! -e "$BUILD_ROOT"/installed-pkg -a ! -e "$BUILD_ROOT"/.build/init_build
     test -e "$BUILD_ROOT"/etc/fstab || touch "$BUILD_ROOT"/etc/fstab
     test ! -e "$BUILD_ROOT"/etc/ld.so.conf -a -e "$BUILD_ROOT"/etc/ld.so.conf.in && cp "$BUILD_ROOT"/etc/ld.so.conf.in "$BUILD_ROOT"/etc/ld.so.conf
     if test -z "$PREPARE_VM" ; then
+       mount_stuff
        run_pkg_scripts
        pkg_initdb
        touch "$BUILD_ROOT"/.init_b_cache/preinstall_finished
@@ -891,6 +908,11 @@ if test ! -e "$BUILD_ROOT"/installed-pkg -a ! -e "$BUILD_ROOT"/.build/init_build
     # mark as preinstalled no longer needed
     rm -rf "$BUILD_ROOT/installed-pkg"
     mkdir -p "$BUILD_ROOT/installed-pkg"
+else
+    # preinstall was already done
+    if test -z "$PREPARE_VM" ; then
+       mount_stuff
+    fi
 fi
 
 if test -n "$PREPARE_VM" ; then
@@ -917,11 +939,15 @@ if test -n "$PREPARE_VM" ; then
     cleanup_and_exit 0
 fi
 
+#
+# finish preinstall if this is a vm continuation
+#
+if test -e "$BUILD_ROOT/.build/init_buildsystem.data" -a ! -e "$BUILD_ROOT/.init_b_cache/preinstall_finished" ; then
+    run_pkg_scripts
+    pkg_initdb
+    touch "$BUILD_ROOT/.init_b_cache/preinstall_finished"
+fi
 
-mkdir -p "$BUILD_ROOT"/proc
-mkdir -p "$BUILD_ROOT"/dev/pts
-mount -n -tproc none "$BUILD_ROOT"/proc 2>/dev/null || true
-mount -n -tdevpts -omode=0620,gid=5 none "$BUILD_ROOT"/dev/pts 2>/dev/null || true
 
 #
 # create .build.binaries directory if requested
@@ -1111,9 +1137,9 @@ cd "$BUILD_ROOT" || cleanup_and_exit 1
 #
 # setup /etc/mtab
 #
-rm -f "$BUILD_ROOT"/etc/mtab
-cp /proc/mounts "$BUILD_ROOT"/etc/mtab
-chmod 644 "$BUILD_ROOT"/etc/mtab
+#init_buildsystem: make /etc/mtab a symlink
+#from patch:https://github.com/openSUSE/obs-build/commit/f0e7d37c811dbde49fcd5b9c8779063f4e87cb74
+ln -sf ../proc/self/mounts $BUILD_ROOT/etc/mtab
 
 #
 # make sure, that our nis is not present in the chroot system
index db23045..f77687c 100644 (file)
--- a/initvm.c
+++ b/initvm.c
@@ -20,7 +20,7 @@
  *
  * AUTHOR
  *      Copyright (c) 2012 James Perkins <james.perkins@linuxfoundation.org>
- *     i                  Adrian Schroeter <adrian@suse.de>
+ *                        Adrian Schroeter <adrian@suse.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 or 3 as
@@ -45,6 +45,7 @@
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
+#include <unistd.h>
 
 /* to enable debugging, compile with -DDEBUG */
 #ifdef DEBUG
@@ -273,7 +274,7 @@ enum okfail binfmt_register(char *datafile, char *regfile)
                        f[name]);
 #endif /* DEBUG */
 
-                /* Does the interpreter exists? */
+        /* Does the interpreter exists? */
                ret=access(f[interpreter], X_OK);
                if (ret != 0) {
 #ifdef DEBUG
@@ -316,29 +317,34 @@ enum okfail binfmt_register(char *datafile, char *regfile)
 int main(int argc, char* argv[], char* env[])
 {
        int retval;
-       char buf[BUFSIZ];
+       char buf[BUFSIZ], *build_dir;
 
-       /* mount proc filesystem if it isn't already */
-       if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL) == -1) {
-               if (errno != EBUSY) {
-                       perror("mount: /proc");
-                       exit(1);
+        if (system("mount | grep 'proc on /proc type proc' >/dev/null") != 0) {
+               /* mount proc filesystem if it isn't already. */
+               if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL) == -1) {
+                       if (errno != EBUSY) {
+                               perror("mount: /proc");
+                               exit(1);
+                       }
+               }
+        }
+
+        /* need to have binfmt_misc loaded already */
+        if (system("mount | grep 'binfmt_misc on /proc/sys/fs/binfmt_misc' >/dev/null") != 0) {
+               /* try to load binfmt module if present, no big deal if it fails */
+               if ((retval = system("/sbin/modprobe binfmt_misc")) != 0) {
+                       DBG(fprintf(stderr, "modprobe binfmt_misc exit code %d\n",
+                               retval));
                }
-       }
-
-       /* try to load binfmt module if present, no big deal if it fails */
-       if ((retval = system("/sbin/modprobe binfmt_misc")) != 0) {
-               DBG(fprintf(stderr, "modprobe binfmt_misc exit code %d\n",
-                       retval));
-       }
 
-       /* mount binfmt filesystem */
-       if (mount("binfmt_misc", SYSFS_BINFMT_MISC, "binfmt_misc", MS_MGC_VAL,
-               NULL) == -1) {
-               if (errno != EBUSY) {
-                       perror("mount: binfmt_misc, " SYSFS_BINFMT_MISC);
+               /* mount binfmt filesystem */
+               if (mount("binfmt_misc", SYSFS_BINFMT_MISC, "binfmt_misc", MS_MGC_VAL,
+                       NULL) == -1) {
+                       if (errno != EBUSY) {
+                               perror("mount: binfmt_misc, " SYSFS_BINFMT_MISC);
+                       }
                }
-       }
+        }
 
        /* verify all paths resulting from this are OK */
        if (!test_access_files(rx_files, R_OK|X_OK, "read/search")) {
@@ -361,10 +367,12 @@ int main(int argc, char* argv[], char* env[])
                exit(1);
        }
 
-       if (getenv("BUILD_DIR"))
-           sprintf(buf, "%s/qemu-reg", getenv("BUILD_DIR"));
+       *buf = 0;
+       build_dir = getenv("BUILD_DIR");
+       if (build_dir && strlen(build_dir) < sizeof(buf) - 10)
+               sprintf(buf, "%s/qemu-reg", build_dir);
 
-        if (!buf || !binfmt_register(buf, SYSFS_BINFMT_MISC_REG)) {
+        if (!*buf || !binfmt_register(buf, SYSFS_BINFMT_MISC_REG)) {
                /* setup all done, do the registration */
                if (!binfmt_register(BINFMT_REGF_0, SYSFS_BINFMT_MISC_REG)) {
                        fprintf(stderr, "%s: failed. Trying alternate binfmt file\n",