Package: dropbear-initramfs
Version: 2020.81-3

I am using dropbear-initramfs on a laptop (running debian 11 / stable
with encrypted rootfs). The intention is that most of the time I will
be entering the cryptsetup password from the laptop keyboard, but
occasionally I might connect the laptop to a local network and unlock
it through the dropbear shell. I think this is similar to the b/964187
use case.

In that bug, you noted difficulties with killing ipconfig with
SIGTERM; the resolution (introducing DROPBEAR_SHUTDOWN_TIMEOUT) left a
race when the cryptsetup password is entered on the console while
there is no attached network cable. By default wait_for_dropbear()
will wait 60 seconds for dropbear to start, while
configure_networking() will try for up to
2+3+4+6+9+16+25+36+64+100=265 seconds to initialize the unconnected
interface. That means an undesired 60 second wait, and the race is
still present.

I was wondering why ipconfig did not respond to SIGTERM, and I can not
reproduce this issue (again, using debian 11 here, so this is with
klibc-utils version 2.0.8-6.1).

The diff below seems to avoid the wait and resolve the race as far as I can see:

--- /usr/share/initramfs-tools/scripts/init-bottom/dropbear.orig
 2021-01-14 12:14:26.000000000 -0800
+++ /usr/share/initramfs-tools/scripts/init-bottom/dropbear
2023-03-04 04:18:18.365776747 -0800
@@ -23,25 +23,34 @@
 IFDOWN="*"
 DROPBEAR_SHUTDOWN_TIMEOUT=60
 if [ -e /etc/dropbear/config ]; then
     . /etc/dropbear/config
 fi

 wait_for_dropbear() {
     local pid exe timer="$DROPBEAR_SHUTDOWN_TIMEOUT"
     pid="$(cat "$PIDFILE" 2>/dev/null)" || return 1

+    # XXX tell configure_networking to stop
+    touch /run/net-dummy.conf
+
     # when configure_networking() is run asynchronously dropbear might
     # not have started yet; ipconfig doesn't react to SIGTERM so we wait
     # for the network stack to be configured (and dropbear to start)
     # rather than terminating the shell and its children
     while [ $timer -gt 0 ] && exe="$(readlink -f "/proc/$pid/exe"
2>/dev/null)"; do
+
+        # XXX kill ipconfig children
+        sed -nr "s/^([0-9]+) \\(ipconfig\\) \\S $pid [0-9]+ .*/\\1/p" \
+            /proc/[0-9]*/stat 2>/dev/null | \
+            while read pidxxx; do kill -TERM "$pidxxx"; done
+
         if [ "$exe" = "$EXE" ]; then
             echo "$pid"
             return 0
         fi
         sleep 1
         timer=$(( timer - 1 ))
     done
     return 1
 }

Hope this helps,

-- 
Michel Lespinasse

Reply via email to