The officially official Devuan Forum!

You are not logged in.

#1 2020-06-27 19:55:57

kuleszdl
Member
Registered: 2018-11-03
Posts: 107  

Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Hi,

after installing the dropbear-initramfs package, everything looked fine. However, after SSH'ing into the busybox environment, each call to

cryptroot-unlock

resulted in the following message:

Try again later

it seems like the following check in cryptroot-unlock never passes:

if [ ! -f "$TABFILE" ] || [ "$TABFILE" -ot "/proc/1" ]; then
        # Too early, init-top/cryptroot hasn't finished yet
        echo "Try again later" >&2
        exit 1
fi

Workaround: Uncomment the line with "exit 1", then everything should work.

Is this check systemd-related?

Offline

#2 2020-06-28 18:56:24

bgstack15
Member
Registered: 2018-02-04
Posts: 205  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

The logic says this:
If (file $TABFILE does not exist) or ( $TABFILE is older than /proc/1) then,
display the error message
return a non-zero result
end-if.

So the creation date of process number 1 (the init, so most likely sysvinit, but doesn't really matter for merely checking the date) is when that process started. So if the tab file (I'm assuming crypttab, as in encrypted filesystem table, but I could be wrong) is older than the current init, then that is a failure state for your check. So it sounds like, in conjunction with the comment, that we need something else to happen first before cryptroot-unlock will work successfully.

So it's not systemd-related. But I don't know the specifics of cyrptroot or dropbear so that's probably all I can help you with.


This space intentionally left blank.

Offline

#3 2020-07-05 19:53:09

kuleszdl
Member
Registered: 2018-11-03
Posts: 107  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Thanks, well the issue here was that I tried to move from an unencrypted to an encrypted system which resulted in a inproper initramfs.

Offline

#4 2023-11-15 18:21:39

Danielsan
Member
Registered: 2020-07-14
Posts: 178  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

I hope any of you can help me here...

I have the same issue, I'd like to try your workaround but I can't find the cryptroot-script in the first place!

find: ‘cryptroot’: No such file or directory

Thanks!

Offline

#5 2023-11-16 00:53:01

Danielsan
Member
Registered: 2020-07-14
Posts: 178  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

kuleszdl wrote:

Hi,

if [ ! -f "$TABFILE" ] || [ "$TABFILE" -ot "/proc/1" ]; then
        # Too early, init-top/cryptroot hasn't finished yet
        echo "Try again later" >&2
        exit 1
fi

Workaround: Uncomment the line with "exit 1", then everything should work.

Is this check systemd-related?

Commenting exit 1 did not solve the issue, unless I misunderstood the fix!

Offline

#6 2023-12-09 15:26:10

unixdan22
Member
Registered: 2022-08-15
Posts: 19  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Here is a shell script I created to install a modified cryptroot-unlock command which skips the timestamp check:

#!/bin/sh

# Problem:
# If /cryptroot/crypttab is older than /proc/1,
# cryptdisks-unlock aborts with the message "Try again later".
# /scripts/init-top/cryptroot is expected to update the timestamp of /cryptroot/crypttab,
# but there is no such script on my target machine.
# /cryptroot/crypttab is already present in the busybox.
#
# Workaround:
# Install a modified /usr/local/bin/cryptdisks-unlock script which does not check the timestamps

ROOTFS_MOUNTPOINT=""

# Create modified version of the cryptroot-unlock script
CRYPTROOT_UNLOCK_SCRIPT="${ROOTFS_MOUNTPOINT}/usr/local/share/cryptsetup/initramfs/bin/cryptroot-unlock"
mkdir -p -- "$(dirname -- "${CRYPTROOT_UNLOCK_SCRIPT}")"
cat > "${CRYPTROOT_UNLOCK_SCRIPT}" <<-"EOF"
#!/bin/busybox ash

# Remotely unlock encrypted volumes.
#
# Copyright © 2015-2018 Guilhem Moulin <guilhem@debian.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# This script was modified to ignore the timestamp of TABFILE

set -ue
PATH=/sbin:/bin

TIMEOUT=10
PASSFIFO=/lib/cryptsetup/passfifo
ASKPASS=/lib/cryptsetup/askpass
UNLOCK_ALL=n

[ -f /lib/cryptsetup/functions ] || return 0
. /lib/cryptsetup/functions
TABFILE="/cryptroot/crypttab"
unset -v IFS

if [ ! -f "$TABFILE" ]; then
	echo "Try again later" >&2
	exit 1
fi

# Print the list of PIDs the executed command of which is $exe.
pgrep_exe() {
	local exe pid
	exe="$(readlink -f -- "$1" 2>/dev/null)" && [ -f "$exe" ] || return 0
	ps -eo pid= | while read pid; do
		[ "$(readlink -f "/proc/$pid/exe")" != "$exe" ] || printf '%d\n' "$pid"
	done
}

# Return 0 if $pid has a file descriptor pointing to $name, and 1
# otherwise.
in_fds() {
	local pid="$1" name fd
	name="$(readlink -f -- "$2" 2>/dev/null)" && [ -e "$name" ] || return 1
	for fd in $(find "/proc/$pid/fd" -type l); do
		[ "$(readlink -f "$fd")" != "$name" ] || return 0
	done
	return 1
}

# Print the PID of the askpass process with a file descriptor opened to
# /lib/cryptsetup/passfifo.
get_askpass_pid() {
	local pid
	for pid in $(pgrep_exe "$ASKPASS"); do
		if in_fds "$pid" "$PASSFIFO"; then
			echo "$pid"
			return 0
		fi
	done
	return 1
}

# Print the number of configured crypt devices that have not been unlocked yet.
count_locked_devices() {
	local COUNT=0
	crypttab_foreach_entry count_locked_devices_callback
	printf '%d\n' "$COUNT"
}
count_locked_devices_callback() {
	dm_blkdevname "$CRYPTTAB_NAME" >/dev/null || COUNT=$(( $COUNT + 1 ))
}

# Wait for askpass, then set $PID (resp. $BIRTH) to the PID (resp.
# birth date) of the cryptsetup process with same $CRYPTTAB_NAME.
wait_for_prompt() {
	local pid timer num_locked_devices=-1 n

	# wait for the fifo
	while :; do
		n=$(count_locked_devices)
		if [ $n -eq 0 ]; then
			# all configured devices have been unlocked, we're done
			exit 0
		elif [ $num_locked_devices -lt 0 ] || [ $n -lt $num_locked_devices ]; then
			# reset $timer if a device was unlocked (for instance using
			# a keyscript) while we were waiting
			timer=$(( 10 * $TIMEOUT ))
		fi
		num_locked_devices=$n

		if pid=$(get_askpass_pid) && [ -p "$PASSFIFO" ]; then
			break
		fi

		usleep 100000
		timer=$(( $timer - 1 ))
		if [ $timer -le 0 ]; then
			echo "Error: Timeout reached while waiting for askpass." >&2
			exit 1
		fi
	done

	# find the cryptsetup process with same $CRYPTTAB_NAME
	local o v
	for o in NAME TRIED OPTION_tries; do
		if v="$(grep -z -m1 "^CRYPTTAB_$o=" "/proc/$pid/environ")"; then
			eval "CRYPTTAB_$o"="\${v#CRYPTTAB_$o=}"
		else
			eval unset -v "CRYPTTAB_$o"
		fi
	done
	if [ -z "${CRYPTTAB_NAME:+x}" ] || [ -z "${CRYPTTAB_TRIED:+x}" ]; then
		return 1
	fi
	if ( ! crypttab_find_entry --quiet "$CRYPTTAB_NAME" ); then
		# use a subshell to avoid polluting our enironment
		echo "Error: Refusing to process unknown device $CRYPTTAB_NAME" >&2
		exit 1
	fi

	for pid in $(pgrep_exe "/sbin/cryptsetup"); do
		if grep -Fxqz "CRYPTTAB_NAME=$CRYPTTAB_NAME" "/proc/$pid/environ"; then
			PID=$pid
			BIRTH=$(stat -c"%Z" "/proc/$PID" 2>/dev/null) || break
			return 0
		fi
	done

	PID=
	BIRTH=
	return 1
}

# Wait until $PID no longer exists or has a birth date greater that
# $BIRTH (ie was reallocated).  Then return with exit value 0 if
# /dev/mapper/$CRYPTTAB_NAME exists, and with exit value 1 if the
# maximum number of tries exceeded.  Otherwise (if the unlocking
# failed), return with value 1.
wait_for_answer() {
	local timer=$(( 10 * $TIMEOUT )) b
	while [ -d "/proc/$PID" ] && b=$(stat -c"%Z" "/proc/$PID" 2>/dev/null) && [ $b -le $BIRTH ]; do
		usleep 100000
		timer=$(( $timer - 1 ))
		if [ $timer -le 0 ]; then
			echo "Error: Timeout reached while waiting for PID $PID." >&2
			exit 1
		fi
	done

	if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
		echo "cryptsetup: $CRYPTTAB_NAME set up successfully" >&2
		[ "$UNLOCK_ALL" = y ] && return 0 || exit 0
	elif [ $(( ${CRYPTTAB_TRIED:-0} + 1 )) -ge ${CRYPTTAB_OPTION_tries:-3} ] &&
			[ ${CRYPTTAB_OPTION_tries:-3} -gt 0 ]; then
		echo "cryptsetup: maximum number of tries exceeded for $CRYPTTAB_NAME" >&2
		exit 1
	else
		echo "cryptsetup: cryptsetup failed, bad password or options?" >&2
		return 1
	fi
}

if [ -t 0 ] && [ -x "$ASKPASS" ]; then
	# interactive mode on a TTY: keep trying until all configured devices have
	# been unlocked or the maximum number of tries exceeded
	UNLOCK_ALL=y
	while :; do
		# note: if the script is not killed before pivot_root it should
		# exit on its own once $TIMEOUT is reached
		if ! wait_for_prompt; then
			usleep 100000
			continue
		fi
		read -rs -p "Please unlock disk $CRYPTTAB_NAME: "; echo
		printf '%s' "$REPLY" >"$PASSFIFO"
		wait_for_answer || true
	done
else
	# non-interactive mode: slurp the passphrase from stdin and exit
	wait_for_prompt || exit 1
	echo "Please unlock disk $CRYPTTAB_NAME"
	cat >"$PASSFIFO"
	wait_for_answer || exit 1
fi

# vim: set filetype=sh :
EOF

chmod +x -- "${CRYPTROOT_UNLOCK_SCRIPT}"

CRYPTROOT_UNLOCK_HOOK="${ROOTFS_MOUNTPOINT}/etc/initramfs-tools/hooks/cryptroot-unlock"
mkdir -p -- "$(dirname -- "${CRYPTROOT_UNLOCK_HOOK}")"
cat > "${CRYPTROOT_UNLOCK_HOOK}" <<-"EOF"
#!/bin/sh

PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case "$1" in
    prereqs)
        prereqs
        exit 0
        ;;
esac

. /usr/share/initramfs-tools/hook-functions
if [ ! -f "${DESTDIR}/usr/local/bin/cryptroot-unlock" ] &&
        ! copy_file script /usr/local/share/cryptsetup/initramfs/bin/cryptroot-unlock /usr/local/bin/cryptroot-unlock; then
    echo "ERROR: Couldn't copy /usr/local/bin/cryptroot-unlock" >&2
    exit 1
fi
EOF
chmod +x -- "${CRYPTROOT_UNLOCK_HOOK}"

Last edited by unixdan22 (2023-12-09 15:40:39)

Offline

#7 2023-12-10 06:40:03

Danielsan
Member
Registered: 2020-07-14
Posts: 178  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

I used this basic workaround:

https://dev1galaxy.org/viewtopic.php?id=6144

Offline

#8 2024-01-07 10:28:47

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Commenting exit 1 did not solve the issue, unless I misunderstood the fix!

Danielsan you needed to re-run

update-initramfs -u -k all

I see you subsequently posted the work around in another thread  (linked from #7), it would have been better to have it in this thread to keep the history together.

Last edited by tux2bsd (2024-01-07 20:51:33)

Offline

#9 2024-01-07 10:34:31

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Taking what Danielsan posted but making the error message meaningful.

diff /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock.bug /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock
33c33
< if [ ! -f "$TABFILE" ] || [ "$TABFILE" -ot "/proc/1" ]; then
---
> if [ ! -f "$TABFILE" ] ; then
35c35
<       echo "Try again later" >&2
---
>       echo "Error: $TABFILE missing." >&2

Also, remember to re-run

update-initramfs -u -k all

Last edited by tux2bsd (2024-01-07 20:20:54)

Offline

#10 2024-01-07 19:51:47

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

https://bugs.devuan.org/cgi/pkgreport.c … -initramfs

There is no maintainer for cryptsetup-initramfs... ...Please do not report new bugs against this package.

Not ideal.

Offline

#11 2024-01-07 20:48:00

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

https://bugs.devuan.org/cgi/bugreport.cgi?bug=829

https://git.devuan.org/devuan/cryptsetu … s/issues/4

Hopefully someone with the right access can add the fix so future package updates don't cause regressions (to the current manual fix).

Offline

#12 2024-01-07 21:31:38

ralph.ronnquist
Administrator
From: Battery Point, Tasmania, AUS
Registered: 2016-11-30
Posts: 1,251  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

cryptsetup-initramfs is not a forked package, so you should report to bugs.debian.org rather.

Online

#13 2024-01-07 22:07:10

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

It is already known that it is not forked (see #10 above).

How does your proposed report to Debian go?
"this thing that works in Debian doesn't work in Devuan"
or do you suggest I lie?
"when I used Debian with sysvinit this doesn't work"
  I'm not doing that:
    a - I don't lie
    b - The fix exists for Devuan, for the problem that surfaces when the package is used in Devuan

Last edited by tux2bsd (2024-01-08 09:51:27)

Offline

#14 2024-01-07 22:20:39

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

OP's post until now...  1288 days

Offline

#15 2024-01-07 22:44:24

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Surely a similar approach is quite common per package, given Devuan is a fork of Debian.

if patch for Debian package then patch file with Devuan specific fix to become Devuan's package
(e.g. cryptsetup-initramfs : /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock Debian's file matches sha256 then patch )
else figure out what changed and make a new patch for Devuan's package containing this file

Last edited by tux2bsd (2024-01-07 23:13:24)

Offline

#16 2024-01-09 05:17:27

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Surely a similar approach is quite common per package, given Devuan is a fork of Debian.

Looks like Amprolla exists for that but it is apparent that rolling a package for a 2 line fix in a shell script is too heavy (yes, I'm aware I suggested a package earlier).

For each user to have to fix a known problem by hand is also poor form.  Part of a Distribution's role is to to mitigate that.

There is a need to distribute reasonable bug fixes to that don't rely on Debian's bug fix process, especially when bugs only surface in Devuan and not stock Debian.  I have no interest making a non-stock Debian with sysvinit to then make it fail just so I can fob off a Devuan bug to Debian's team, that's gaming the system.

If there was a stock Debian bug fix found that can go to Debian in parallel, we all know it takes a while for those to eventuate.  There's benefit there too, earlier tracked fixes in Devuan.  When those fixes do arrive via Debian (after some years) they no longer need to be distributed.

I'm well aware the bug in this thread does not affect many people, though that that shouldn't matter.

OP's post until now...  1289 days

Offline

#17 2024-04-20 06:10:37

tux2bsd
Member
Registered: 2023-12-15
Posts: 21  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

Dropbear package updated re-introducing the bug. 

Workaround: https://dev1galaxy.org/viewtopic.php?pid=46994#p46994

OP's post until now... 1,392 days

Last edited by tux2bsd (2024-04-20 06:13:12)

Offline

#18 2024-09-27 20:42:15

clemmerson
Member
Registered: 2024-09-27
Posts: 1  

Re: Dropbear-initramfs: cryptroot-unlock says "Try again later" forever

This is how I fixed it. Seems to be a timing issue.

I edited /usr/share/cryptsetup/initramfs/bin/cryptroot-unlock

Found the block

if [ ! -f "$TABFILE" ] || [ "$TABFILE" -ot "/proc/1" ]; then
    echo "Try again later" >&2
    exit 1
fi

And then changed it to this

MAX_RETRIES=10
RETRY_INTERVAL=3

# Retry mechanism to check if TABFILE is ready
for i in $(seq 1 $MAX_RETRIES); do
    if [ -f "$TABFILE" ] && [ "$TABFILE" -nt "/proc/1" ]; then
        break
    fi
    
    if [ $i -eq $MAX_RETRIES ]; then
        echo "Error: $TABFILE still not ready after $MAX_RETRIES attempts. Exiting." >&2
        exit 1
    fi

    echo "Waiting for cryptroot to be ready... attempt $i/$MAX_RETRIES"
    sleep $RETRY_INTERVAL
done

Don't forget to apply changes

update-initramfs -u -k all

Offline

Board footer