Package: nbd-client
Version: 1:2.9.23-3
Severity: important
Tags: patch

If the user answers some configuration questions incorrectly a faulty
/etc/nbd-client configuration file is created. /etc/init.d/nbd-client isn't
robust against this and the system fails to boot because /etc/init.d/nbd-client
hangs. It's not possible to interrupt at this point, nor is it possible to
recover the system by booting to single-user since the script runs even in
state S. I had to boot to a live CD to get out of the mess.

The problem is two-fold:

1. The debconf process allows a faulty configuration to be created
2. The init.d script doesn't handle a faulty configuration properly

I haven't tried to fix (1) since it's always possible for the user to create a
bad configuration (eg by giving bad file paths) so the software needs to be
able to handle this, and shouldn't cause the system to be unbootable.

Some bad configurations result in an error message from nbd and the system
continues with booting. However, the init.d script is poorly written in that it
doesn't double-quote key variable values, causing strange behaviours when these
variables are null, and eventually the hang is caused by calling grep with a
single argument on line 159, because NBD_DEVICE[0] is null.

My faulty configuration had NBD_TYPE[0]="f" and NBD_DEVICE[0]="", so the device
wasn't being skipped in the test on line 150. I manually edited the file to set
NBD_TYPE[0]="" but every time there was an upgrade to nbd-client it went back
to "f" and I had a non-bootable system again.

The patch wraps all configuration-derived variables in double-quotes.

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (900, 'testing')
Architecture: i386 (x86_64)

Kernel: Linux 2.6.39-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages nbd-client depends on:
ii  debconf [debconf-2.0]      1.5.40        Debian configuration management sy
ii  initscripts                2.88dsf-13.11 scripts for initializing and shutt
ii  libc6                      2.13-10       Embedded GNU C Library: Shared lib

nbd-client recommends no packages.

nbd-client suggests no packages.

-- debconf information:
  nbd-client/device:
  nbd-client/host:
  nbd-client/no-auto-config:
  nbd-client/extra:
* nbd-client/killall: false
  nbd-client/port:
  nbd-client/type: raw
* nbd-client/number: 0
>From d9b70ba363b598eb3e7c0513c9b6af27965d2b70 Mon Sep 17 00:00:00 2001
From: Neil Mayhew <neil_may...@users.sourceforge.net>
Date: Mon, 31 Jan 2011 17:12:48 -0700
Subject: [PATCH] Increase robustness against faulty configurations

This was causing boot hangups with certain automatically-created
configurations.
---
 debian/nbd-client.init.d   |   26 +++++++++++++-------------
 debian/nbd-client.postinst |    6 +++++-
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/debian/nbd-client.init.d b/debian/nbd-client.init.d
index 9beffc3..ffbe340 100644
--- a/debian/nbd-client.init.d
+++ b/debian/nbd-client.init.d
@@ -38,9 +38,9 @@ test -x $DAEMON || exit 0
 get_devices() {
     DEVICES=
     i=0
-    while [ ! -z ${NBD_TYPE[$i]} ]
+    while [ ! -z "${NBD_TYPE[$i]}" ]
     do
-       if [ ${NBD_TYPE[$i]} == "$1" ]
+       if [ "${NBD_TYPE[$i]}" == "$1" ]
        then
            DEVICES="$DEVICES ${NBD_DEVICE[$i]}"
        fi
@@ -94,16 +94,16 @@ case "$1" in
        modprobe nbd
        echo -n 'Connecting...'
        i=0
-       while [ ! -z ${NBD_TYPE[$i]} ]
+       while [ ! -z "${NBD_TYPE[$i]}" ]
          do
          # cfq deadlocks NBD devices, so switch to something else if cfq is
          # selected by default
          # This doesn't take into account non-udev devnames, but since
          # there's really no other option these days...
-         if grep '\[cfq\]' 
/sys/block/${NBD_DEVICE[$i]/\/dev\//}/queue/scheduler >/dev/null; then
-               echo deadline > 
/sys/block/${NBD_DEVICE[$i]/\/dev\//}/queue/scheduler
+         if grep '\[cfq\]' 
"/sys/block/${NBD_DEVICE[$i]/\/dev\//}/queue/scheduler" >/dev/null; then
+               echo deadline > 
"/sys/block/${NBD_DEVICE[$i]/\/dev\//}/queue/scheduler"
          fi
-         if nbd-client -c ${NBD_DEVICE[$i]} >/dev/null
+         if nbd-client -c "${NBD_DEVICE[$i]}" >/dev/null
          then
                echo "${NBD_DEVICE[$i]} already connected, skipping..."
          else
@@ -113,7 +113,7 @@ case "$1" in
                else
                        name=""
                fi
-               $DAEMON ${NBD_HOST[$i]} $name ${NBD_PORT[$i]} ${NBD_DEVICE[$i]} 
${NBD_EXTRA[$i]}
+               $DAEMON "${NBD_HOST[$i]}" $name "${NBD_PORT[$i]}" 
"${NBD_DEVICE[$i]}" "${NBD_EXTRA[$i]}"
                echo "connected ${NBD_DEVICE[$i]}"
          fi
          i=$(($i + 1))
@@ -147,16 +147,16 @@ case "$1" in
     activate)
        echo 'Activating...'
        i=0
-       while [ ! -z ${NBD_TYPE[$i]} ]
+       while [ ! -z "${NBD_TYPE[$i]}" ]
        do
          case ${NBD_TYPE[$i]} in
              "s")
-                 /sbin/mkswap ${NBD_DEVICE[$i]}
-                 /sbin/swapon ${NBD_DEVICE[$i]}
+                 /sbin/mkswap "${NBD_DEVICE[$i]}"
+                 /sbin/swapon "${NBD_DEVICE[$i]}"
                  echo "${NBD_DEVICE[$i]}: swap activated."
                  ;;
              "f")
-                 line=$(grep ${NBD_DEVICE[$i]} /etc/fstab | grep "_netdev")
+                 line=$(grep "${NBD_DEVICE[$i]}" /etc/fstab | grep "_netdev")
                  if [ -z "$line" ]
                  then
                    # sysvinit takes care of these.
@@ -164,10 +164,10 @@ case "$1" in
                    case "$TERM" in
                      dumb|network|unknown|"") spinner="" ;;
                    esac
-                   /sbin/fsck $spinner -a ${NBD_DEVICE[$i]}
+                   /sbin/fsck $spinner -a "${NBD_DEVICE[$i]}"
                    if [ $? -lt 2 ]
                        then
-                       /bin/mount ${NBD_DEVICE[$i]}
+                       /bin/mount "${NBD_DEVICE[$i]}"
                        echo "${NBD_DEVICE[$i]}: filesystem mounted."
                    else
                        echo "fsck of ${NBD_DEVICE[$i]} failed. Not mounting."
diff --git a/debian/nbd-client.postinst b/debian/nbd-client.postinst
index 75d3cf4..3c61426 100644
--- a/debian/nbd-client.postinst
+++ b/debian/nbd-client.postinst
@@ -64,7 +64,7 @@ case "$1" in
                     device=$RET
                    db_get nbd-client/extra$i
                    extra=$RET
-                    [ -e $device ] || mknod $device b 43 $(( $i + 0 ))
+                    [ -e "$device" ] || mknod "$device" b 43 $(( $i + 0 ))
                     db_get nbd-client/type$i
                     case "$RET" in
                         "swap")
@@ -77,6 +77,10 @@ case "$1" in
                             type_="r"
                             ;;
                     esac
+                    if [ -z "$host" -o -z "$port" -o -z "$device" ]
+                    then
+                        type_= # Ensure device will be skipped
+                    fi
                     i=$(( $i + 0 ))
                     sed -i -e 's:\(^NBD_DEVICE\['$i'\]\=\).*:\1"'$device'":g' 
-e \
                         's/\(^NBD_TYPE\['$i'\]=\).*/\1"'$type_'"/g' -e \
-- 
1.7.5.4

Reply via email to