NetBSD Problem Report #35547

From www@NetBSD.org  Sun Feb  4 17:54:57 2007
Return-Path: <www@NetBSD.org>
Received: by narn.NetBSD.org (Postfix, from userid 31301)
	id 41E6063BAF4; Sun,  4 Feb 2007 17:54:57 +0000 (UTC)
Message-Id: <20070204175457.41E6063BAF4@narn.NetBSD.org>
Date: Sun,  4 Feb 2007 17:54:57 +0000 (UTC)
From: anne@encs.concordia.ca
Reply-To: anne@encs.concordia.ca
To: gnats-bugs@NetBSD.org
Subject: add timeout to cgdconfig
X-Send-Pr-Version: www-1.0

>Number:         35547
>Category:       bin
>Synopsis:       add timeout to cgdconfig
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 04 17:55:00 +0000 2007
>Last-Modified:  Sun Feb 04 21:40:01 +0000 2007
>Originator:     Anne Bennett
>Release:        3.1
>Organization:
>Environment:
NetBSD quill.porcupine.qc.ca 3.1 NetBSD 3.1 (QUILL_I386) #1: Thu Jan 18 23:29:30 EST 2007  anne@quill.porcupine.qc.ca:/usr/src/sys/arch/i386/compile/QUILL_I386 i386

>Description:
Modify cgdconfig to allow a timeout (e.g. option "-t seconds"),
or modify /etc/rc.d/cgd to check for user presence before trying
cgdconfig.  In other words, if there's no user input in some
number of seconds, give up and exit.

Reason: if a system has to boot without the sysadmin present, it
should be possible for it to come up without the CGDs (assuming
of course that the sysadmin didn't put any boot-critical data
on a CGD!), as opposed to stalling the boot indefinitely while
it waits for a human to show up and type in the password.

For example, there is only a small amount of sensitive data on
my workstation, and if there's a crash or a power failure while
I'm away, I'd like the system to come up; I can then log in 
remotely and bring up the CGD (from a trusted system, of course!).
It would be very inconvenient to have to do without the system
entirely until I can be physically present to help it boot, just
because I have a little bit of encrypted data.

I've managed to hack this in a rather ugly way for now (using
/etc/rc.d/cgd), but it would be ever so much better to just be
able to add 'cgd_flags="-t 15"' to rc.local, for example.  (Not
being a frequent C programmer, I didn't try such a patch myself.)

Note that I've had to make some additional changes to make this 
work, and something like them would also be required for a cleaner
implementation: (a) make cgd filesystems "noauto" in fstab to avoid
unintended mounts [or you could just let them fail], (b) put "0"
in the "fsck pass" field in fstab, otherwise an attempt will be made
to fsck the filesystem on the unconfigured device, and the boot will 
fail, (c) added a setting cgd_bypass_noauto="list of mountpoints"
to rc.local, to permit cgd filesystems to be found, fsck'd, and 
mounted but only if the underlying device is configured, (d) added
a script /etc/rc.d/mountcgdbypass to do this.

This seems Rube-Goldbergesque, and I can't help but think there
must be a better way.  I could probably simplify it considerably
if I never fsck'd the CGD filesystems, for example: then it would
be sufficient to let the mount attempts (of the unconfigured device)
fail and the boot continue.  It would be neat of there were an fstab
option that made it possible to fsck a filesystem only if its
underlying device was configured, but I have no idea how difficult
that would be.

So for now, my request is basically to add a timeout option to
cdgconfig.  If anyone else finds this idea useful and would like
to "fix it", that would be amazing.

Anne.

>How-To-Repeat:
Try to boot a system which wants to mount cgd filesystems
during the boot sequence, but don't enter the cgd password.
The boot will stall.
>Fix:
Here are some horrible hacks.  There has to be a better way.

-------------------------------------------------------
#!/bin/sh
#
# $NetBSD: cgd,v 1.5 2005/03/02 19:09:22 tv Exp $
#

# PROVIDE: disks

# 2007/01/21 Anne Bennett: proceed only if user standing by with password.
#  This avoids indefinite boot hang if no on is there.
#  WARNING: make sure no attempt is made to "fsck" filesystems on
#  potentially unconfigured devices.
timeout=15

$_rc_subr_loaded . /etc/rc.subr

name="cgd"
rcvar=$name
start_cmd="cgd_start"
stop_cmd=":"

cgd_start()
{
        if [ -f /etc/cgd/cgd.conf ]; then
                answer=""
                echo    "^GAre you ready to configure the CGD?"
                echo -n "^GPlease respond within $timeout seconds (y or n): "

                # Timeout for stty is in tenths of a second:
                stty_to=`expr 10 \* $timeout`
                # Keep old tty settings:
                oldtty="`stty -g`"
                # Turn off canonical mode, turn off signals, enforce timeout:
                stty -icanon min 0 time $stty_to -isig
                # Try to get user input:
                read answer
                # Put terminal back to normal:
                stty "$oldtty"

                if [ -z $answer ] ; then 
                        echo "No response within $timeout seconds; skipping CGD 
configuration."
                else
                        if expr "$answer" : "[Yy]" >/dev/null ; then
                                echo "Configuring CGD devices."
                                cgdconfig -C
                        else
                                echo "Okay, skipping CGD configuration."
                        fi
                fi 

        fi
}

load_rc_config $name
run_rc_command "$1"

-------------------------------------------------------
#!/bin/sh
#
# $NetBSD: mountcgdbypass,v 1.0 2007/01/21 15:00:00 anne Exp $
#

# REQUIRE: disks
# BEFORE:  DAEMON

$_rc_subr_loaded . /etc/rc.subr

name="mountcgdbypass"
start_cmd="mountcgdbypass_start"
stop_cmd=":"

mountcgdbypass_start()
{
        #       Mount `cgd' filesystems specified in $cgd_bypass_noauto,
        #       but only if their cgd is configured.
        #

        if [ -z "$cgd_bypass_noauto" ]; then
                exit
        fi

        # Of the specified list, keep only those not already mounted.
        mount_candidates="`
        for _fs in $cgd_bypass_noauto; do
                mount | (
                        _ismounted=false
                        while read what _on on _type type; do
                                if [ $on = $_fs ]; then
                                        _ismounted=true
                                fi
                        done
                        if $_ismounted; then
                                :
                        else
                                echo $_fs
                        fi
                )
        done`"
        mount_candidates="`echo $mount_candidates`"

        if [ -z "$mount_candidates" ]; then
                exit
        fi

        # Of the remaining candidates, keep only those whose dev is configured.
        configured_disks="`sysctl -n hw.disknames`"
        ready_candidates="`
        for disk in $configured_disks ; do
                ( while read fs mtpt type opt fsck1 fsck2 ; do
                        case $fs in
                                /dev/$disk[a-p])
                                        if expr \" $mount_candidates \" : \".* $
mtpt \" > /dev/null ; then
                                                echo $mtpt
                                        fi
                                        ;;
                                *)
                                        ;;
                        esac
                done ) < /etc/fstab
        done`"
        ready_candidates="`echo $ready_candidates`"


        # For the remaining candidates, fsck and mount if okay
        for fs in $ready_candidates ; do
                echo Checking and mounting bypassed CGD filesystem $fs
                fsck -p $fs && mount $fs
        done

}

load_rc_config $name
run_rc_command "$1"

-------------------------------------------------------

>Audit-Trail:
From: Lubomir Sedlacik <salo@Xtrmntr.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: bin/35547: add timeout to cgdconfig
Date: Sun, 4 Feb 2007 21:31:06 +0100

 On Sun, Feb 04, 2007 at 05:55:00PM +0000, anne@encs.concordia.ca wrote:
 > cgd_start()
 > {
 >         if [ -f /etc/cgd/cgd.conf ]; then
 >                 answer=3D""
 >                 echo    "^GAre you ready to configure the CGD?"
 >                 echo -n "^GPlease respond within $timeout seconds (y or n=
 ): "

 what if you have e.g., two cgd(4) volumes, where one is swap and it can
 be configured just fine without any user interaction? =20

 i think the rc.d script is the wrong place to do this kind of things.
 ideally, there would be a per-volume option which could be added to
 cgd.conf.


 regards,

 --=20
 -- Lubomir Sedlacik <salo@{NetBSD,Xtrmntr,silcnet}.org>   --

From: Anne Bennett <anne@encs.concordia.ca>
To: gnats-bugs@NetBSD.org
Cc: gnats-admin@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: bin/35547: add timeout to cgdconfig
Date: Sun, 04 Feb 2007 16:35:50 -0500

 Lubomir Sedlacik <salo@Xtrmntr.org> comments on my request for improvement:

 >  what if you have e.g., two cgd(4) volumes, where one is swap and it can
 >  be configured just fine without any user interaction?
 >  
 >  i think the rc.d script is the wrong place to do this kind of things.
 >  ideally, there would be a per-volume option which could be added to
 >  cgd.conf.

 My first though was that this would be even better than my proposal of a
 "-t seconds" option to cgdconfig, but then two tihngs occurred to me:

   - no point having a separate timeout for all the "user interaction
     required" cgd volumes, since either the user is sitting there or
     she isn't, so there's no point timing out more than once, and

   - cgdconfig know when user interaction is needed, since it prompts
     for it, so the "-t seconds" option should affect only volumes
     that require user interaction.

 My thoughts, based on your comment:

   - globals: timeout_requested (0 by default, else -t argument)
              timeout_has_been_done (starts false)
              a_user_is_present (starts false)

   - for each cgd volume:
       if user interaction needed for this volume
          if ! a_user_is_present and ! timeout_has_been_done and timeout_requested
              start timeout:
                if user indicates they are present:
                  set a_user_is_present
                  set timeout_has_been_done
                else
                  set timeout_has_been_done

          if ! timeout_requested or a_user_is_present
            proceed with requesting password
            configure volume
          else
            skip this one
       else (no user interaction needed for this volume)
         configure volume


 Anne.
 -- 
 Ms. Anne Bennett, Senior Sysadmin, ENCS, Concordia University, Montreal H3G 1M8
 anne@encs.concordia.ca                                    +1 514 848-2424 x2285

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.