You are not logged in.
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
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
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
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
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
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
I used this basic workaround:
Offline
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
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
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
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
cryptsetup-initramfs is not a forked package, so you should report to bugs.debian.org rather.
Online
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
OP's post until now... 1288 days
Offline
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
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
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
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