SPS · log · files · refs · tags · releases · people · languages · GitHub · commit
2909919
mkiso: copy the program interpreter to the path the ELF names
Parents
Stat
bin/mkiso | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+)
Diff
diff --git a/bin/mkiso b/bin/mkiso
index fff7ea9..0f66851 100755
--- a/bin/mkiso
+++ b/bin/mkiso
@@ -290,9 +290,42 @@ mkiso_copy_libs()
esac
;;
esac
+ # An ldd line reads "WANTED => RESOLVED". For a library, WANTED is
+ # a soname the loader searches for, and copying RESOLVED is right.
+ # For the program interpreter, WANTED is the absolute path baked
+ # into the ELF, and the kernel opens exactly that. When the two
+ # differ because the host reaches the loader through a symlinked
+ # lib64, copying only RESOLVED leaves the interpreter missing at
+ # the one path that matters, and exec fails with ENOENT. The
+ # kernel then reports it as "can't execute /sbin/init".
+ case $mkiso_line in
+ *" => "*)
+ mkiso_wanted=${mkiso_line%% => *}
+ mkiso_wanted=${mkiso_wanted## }
+ mkiso_wanted=${mkiso_wanted# }
+ case $mkiso_wanted in
+ /*)
+ [ "$mkiso_wanted" = "$mkiso_lib" ] ||
+ mkiso_copy_as "$mkiso_lib" "$mkiso_wanted"
+ ;;
+ esac
+ ;;
+ esac
done
}
+# Place the contents of an existing host file at a specific path in the live
+# root, which may differ from where it lives on the host.
+mkiso_copy_as()
+{
+ mkiso_src=$1
+ mkiso_dst=$2
+ [ -n "$mkiso_src" ] && [ -e "$mkiso_src" ] || return 0
+ [ -e "$mkiso_live$mkiso_dst" ] && return 0
+ mkdir -p "$mkiso_live${mkiso_dst%/*}" || return 0
+ cp -a "$mkiso_src" "$mkiso_live$mkiso_dst" 2>/dev/null || return 0
+}
+
# close_libs only walks bin/sbin. cc1 (libmpc/libisl) and Mesa DRI
# (libSPIRV-Tools) are dlopened helpers, so a seeded disc can have gcc
# and still fail "C compiler cannot create executables", and Plasma can
@@ -1590,6 +1623,54 @@ mkiso_install_pid1()
fi
[ -x "$mkiso_live/sbin/init" ] ||
sps_die "$SPS_EX_PACKAGE" "failed to install /sbin/init"
+ mkiso_verify_init
+}
+
+# /sbin/init existing is not the same as /sbin/init being runnable. A dangling
+# symlink, a missing program interpreter, or a missing shared library all make
+# the kernel fail switch_root with ENOENT, which it reports as "can't execute
+# /sbin/init: No such file or directory". That panic is only visible after the
+# disc is written and booted, so check it here while it is still cheap.
+mkiso_verify_init()
+{
+ mkiso_init_target=$mkiso_live/sbin/init
+ mkiso_init_hops=0
+ while [ -L "$mkiso_init_target" ]; do
+ mkiso_init_hops=$((mkiso_init_hops + 1))
+ [ "$mkiso_init_hops" -lt 10 ] ||
+ sps_die "$SPS_EX_PACKAGE" "/sbin/init is a symlink loop"
+ mkiso_init_link=$(readlink "$mkiso_init_target")
+ case $mkiso_init_link in
+ /*) mkiso_init_target=$mkiso_live$mkiso_init_link ;;
+ *) mkiso_init_target=${mkiso_init_target%/*}/$mkiso_init_link ;;
+ esac
+ done
+ [ -f "$mkiso_init_target" ] ||
+ sps_die "$SPS_EX_PACKAGE" \
+ "/sbin/init resolves to ${mkiso_init_target#$mkiso_live}, which is not in the live root"
+ [ -x "$mkiso_init_target" ] ||
+ sps_die "$SPS_EX_PACKAGE" "/sbin/init is not executable"
+
+ command -v readelf >/dev/null 2>&1 || return 0
+ # readelf prints " [ 0] /lib64/ld-linux-x86-64.so.2"; take the
+ # whole path after the offset field rather than matching on "ld-",
+ # which a greedy expression would clip to the last path component.
+ mkiso_init_interp=$(readelf -p .interp "$mkiso_init_target" 2>/dev/null |
+ sed -n 's/^[[:space:]]*\[[^]]*\][[:space:]]*\(\/.*\)$/\1/p' |
+ head -n 1)
+ if [ -n "$mkiso_init_interp" ] &&
+ [ ! -e "$mkiso_live$mkiso_init_interp" ]
+ then
+ sps_die "$SPS_EX_PACKAGE" \
+ "PID 1 needs interpreter $mkiso_init_interp, which is not in the live root"
+ fi
+
+ command -v ldd >/dev/null 2>&1 || return 0
+ mkiso_init_missing=$(ldd "$mkiso_init_target" 2>/dev/null |
+ sed -n 's/^[[:space:]]*\([^ ]*\) => not found.*/\1/p')
+ [ -z "$mkiso_init_missing" ] ||
+ printf '%s: warning: PID 1 has unresolved libraries on the host: %s\n' \
+ "$sps_prog" "$(printf '%s' "$mkiso_init_missing" | tr '\n' ' ')" >&2
}
# --- live root contents -------------------------------------------------