On 12/01/16 06:05 PM, Marco d'Itri wrote:
On Jan 12, Jason Rhinelander <jager...@jagerman.com> wrote:

Thank you for testing the conversion program, for a start!

I installed usrmerge, and got the following during configuration:
This is expected and not a bug.

Right (was just reporting it for context).

At this point, I examined the disk layout, and noticed that basically
everything* in /{bin,sbin,lib} had been moved to /usr/{bin,sbin,lib}, and
replaced with symlinks in /{bin,sbin,lib}, but /{bin,sbin,lib} still
existed as real directories (not symlinks).
If you got at that point then everything in the directories was either
a directory or a symlink.

Yes, it appears it had just the final move-away-and-symlink step left.

Since I couldn't figure out which daemon was causing the problem, I
rebooted the system as suggested in the usrmerge configure error
messages.  It didn't come back up: it failed to start with an error that
/sbin/init was not found on the disk.  Oddly, however, I could run ls
/sbin/init which *did* show an existing symlink and target.
Did you get a "No init found. Try passing init= bootarg." message,
exactly?
This check in the initramfs it is supposed to cope with absolute
symlinks, but I did not test this exact condition and it is the only
possible failure I can think about right now.

The error was:

Target filesystem doesn't have requested /sbin/init

and so it indeed appears to be validate_init in initramfs-tools/init not coping with the intermediate usrmerge setup.

Taking a quick look at it, it looks like validate_init will only handle a *single* absolute symlink, but in this particular case there are two (absolute) symlinks:

/sbin/init -> /usr/sbin/init
/usr/sbin/init -> /lib/systemd/systemd

and so it resolves the first to ${rootmnt}/usr/sbin/init, but not the second, and so init is still a broken symlink.

I've attached a patch for initramfs-tools to cope with this by resolving symlinks in a loop (up to a maximum of 10 times, to avoid an infinite loop for potential symlink cycles) instead of just once, which should fix the problem. It seems to work with an artificial nest of various symlinks (both absolute and relative) that I created, though I didn't replicate the usrmerge intermediate step to actually test it there.


Jason Rhinelander
--- a/init	2016-01-13 10:50:25.928550244 -0500
+++ b/init	2016-01-13 11:08:19.900426244 -0500
@@ -234,15 +234,20 @@
 	checktarget="${1}"
 
 	# Work around absolute symlinks
-	if [ -d "${rootmnt}" ] && [ -h "${rootmnt}${checktarget}" ]; then
-		checktarget="$(readlink "${rootmnt}${checktarget}")"
-		case "$checktarget" in
-		/*)
-			;;
-		*)
-			checktarget="${1%/*}/$checktarget"
-			;;
-		esac
+	if [ -d "${rootmnt}" ]; then
+        readlink_count=0
+        while [ -h "${rootmnt}${checktarget}" ] && [ "$readlink_count" -lt 10 ]; do
+            lasttarget="${checktarget}"
+            checktarget="$(readlink "${rootmnt}${checktarget}")"
+            readlink_count=$((readlink_count+1))
+            case "$checktarget" in
+            /*)
+                ;;
+            *)
+                checktarget="${lasttarget%/*}/$checktarget"
+                ;;
+            esac
+        done
 	fi
 
 	# Make sure the specified init can be executed

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to