Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Jun 2001 01:26:58 -0600
From:      Chris Wasser <cwasser@v-wave.com>
To:        arch@FreeBSD.org
Subject:   changes to /etc/rc*
Message-ID:  <20010619012658.A53486@skunkworks.arpa.mil>

next in thread | raw e-mail | index | archive | help
 Ok, since there is a lot for me to cover here, I'm going to answer
everyone in one big related email so please bear with me (it's a long
read to various parties). I will only be sending this to -arch so if
someone feels others should receive this, then please forward it to
the appropiate parties.

 Everyone else is more then welcome to put their two cents into what I
have to say :)

 (original message from lukem@wasabisystems.com has remained unabridged)

>Date: Tue, 19 Jun 2001 10:23:06 +1000
>From: Luke Mewburn <lukem@wasabisystems.com>
>To: Chris Wasser <cwasser@v-wave.com>
>Subject: Re: NetBSD /etc/rc.subr diff
>Cc: Sheldon Hearn <sheldonh@starjuice.net>
>Reply-To: Luke Mewburn <lukem@wasabisystems.com>
>
>>On Mon, Jun 18, 2001 at 02:15:24PM -0600, Chris Wasser wrote:
>>  Hi,
>>
>>  Attached is a diff to /etc/rc.subr for NetBSD (and recently imported
>> into FreeBSD) which is designed to reduce the potential for false
>> positive hits in gathering process information for the rc init
>> system.
>>
>>  Please note the diff is applied against the rc.subr in FreeBSD's
>> tag=HEAD rather then the actual NetBSD /etc/rc.subr, however the
>> differences between the two are very minor and should have no
>> problems merging this diff.
>>
>>  I'm interested to hear any comments, suggestions or just general
>> questions you may have on this diff and would be happy to answer any
>> posed.
>
>Hi Chris.
>
>I'm not sure which version of rc.subr was used in the FreeBSD import,
>but it looks a little old, because in rev 1.30 in NetBSD I changed
>that particular code to use "case" instead of "if", etc.

 I based my diff off the rc.subr (v1.28) found at:
 http://www.FreeBSD.org/cgi/cvsweb.cgi/src/etc/rc.subr?only_with_tag=HEAD

 Again, I noted this diff was made against rc.subr that I found in the
FreeBSD cvs tree.

>
>Other comments:
>
>        - There's no need to check if a command matches
>                "*/$_procnamebn"
>          because $_procnamebn is the basename of $_procname
>          (that's that
>                _procnamebn=${_procname##*/}
>          does)
>

 In this I disagree entirely. Not that in $_procnamebn isn't a valid
match-term, but that searching for */$_procnamebn is also perfectly
valid, and can reduce the potential for false matches, consider the
following processes 'qmail-smtpd' and 'cron':

/root# ps -ax -o pid,command | grep cron
24404 /usr/sbin/cron
53287 grep cron

/root# ps -ax -o pid,command | grep qmail-smtpd
53289 grep qmail-smtpd

 As you can see, cron is found, but only grep is displayed for
qmail-smtpd, this matching system would fail to discover the process id
for qmail-smtpd which indeed is running using my calling and matching
scheme for process checks:

/root# ps -axwww -o pid,command | grep cron
24404 /usr/sbin/cron
53293 grep cron

/root# ps -axwww -o pid,command | grep qmail-smtpd
53373 grep qmail-smtpd
  328 /usr/local/bin/tcpserver -v -R -x/etc/tcp.smtp.cdb -u82 -g81 0
      smtp /usr/local/bin/fixcrio /usr/local/bin/rblsmtpd -b
      -rrelays.mail-abuse.org /var/qmail/bin/qmail-smtpd

 By matching for leading / (and thus, indicative of absolute pathed
execution) it's quite easy to find the correct PID of the process in
question. Almost all the services started from FreeBSD (unsure about
NetBSD, I imagine it's the same) rc are absolutely pathed when they're
executed [if that's the correct term] for example, sshd in which I've
only configured sshd_flags and sshd_enable in /etc/rc.conf:

/root# ps -axwww -o pid,command | grep sshd
25063 /usr/sbin/sshd -p 22
53375 grep sshd

 Which in turn is set up initially from /etc/default/rc.conf:

/root# grep sshd /etc/defaults/rc.conf 
sshd_enable="NO"                # Enable sshd
sshd_program="/usr/sbin/sshd"   # path to sshd, if you want a different one.
sshd_flags=""                   # Additional flags for sshd.

 So matching for a leading / is not only a good thing, but can produce
results faster and more accurately (because search 'term' has been
increased, more characters to match is a better match no?)

 I have tested your theory about not needing this matching, and
removing the relevant section of shellcode which preforms the check
against */_procnamebn fails to find qmail-smtpd in the above example,
thus rc will fail to find the process, or mark it as down or handle it
however it chooses.

 You can find a shellscript designed to preform this same check
@ http://plaza.v-wave.com/cwasser/proc-read.sh (see script for details)
to test this theory yourself.

>        - I use the test for pid == "PID" to skip the first entry
>          which is the header line from ps because
>                a) there's no valid PID called "PID", so my test isn't
>                   going to get a false match
>                b) tail and sort are in /usr/bin, which may not be
>                   mounted when this code runs.
>                c) the current code (using case not if) is fast
>
>
>        - I'm not sure why you call "ps -www ...", and also check all
>          the command arguments of the process for matching process names
>          to find a PID.
>          What's the rationale here?

 By using sort and tail, this check for pid == "PID" is uneccessary as
unneeded information is weeded out before it's processed by the
shellcode. Not only does it remove the need to check for ps(1) headers,
but it also sorts the output in a manner most efficient to producing
matches, what I mean by this is the same matches /etc/rc.subr is trying
to make:

 $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"

 Are logically sorted to the top of the list after tail and sort are
finished, producing matches on these somewhat ambigious matches (a good
example is sendmail, or tcpserver) which use setproctitle(3) and again,
I re-iterate, it's my feeling that adding another match-term for
absolute pathed process entries will also produce faster, more accurate
results (to some extent):

 For example (I will show only relevant sections as they appear):

/root# ps -axwww -o pid,command | tail +2 | sort +1
    4  (bufdaemon)
    2  (pagedaemon)
53396  (sh)
  388 -csh (csh)
  440 -csh (csh)
  470 ./irc -p 6667 TDF irc.powersurfr.com
24404 /usr/sbin/cron
  300 /usr/sbin/moused -3 -F 200 -r high -p /dev/psm0
  210 /usr/sbin/portmap
25063 /usr/sbin/sshd -p 22
  381 /usr/sbin/syslogd -ss
53514 ps -axwww -o pid,command
  325 qmail-clean
17173 sshd: flatline (sshd)
34624 sshd: flatline (sshd)

 However, seeing as how sort and tail may not be available for usage due
to unmounted filesystem, the logical choice then is instead of matching
against _npid one could match against _arg0 as a measure to removing
irrelevant information. For example:

NetBSD cvsweb directory for /etc/rc.subr (v1.37):
http://cvsweb.netbsd.org/bsdweb.cgi/basesrc/etc/rc.subr?only_with_tag=HEAD

 In check_process() and check_pidfile() you use similar checks:

    case "$_npid" in
        PID)
            continue
            ;;
    esac
    case "$_arg0" in
        $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})")
            echo $_npid
            return
            ;;
    esac

 This would be more efficient if you matched COMMAND in $_arg0
case-select, for example:

    case "$_arg0" in
        COMMAND)
            continue
            ;;
        $_procname|$_procnamebn ...
            ...
            ...
    esac

 Unless 'ps -ax ...' on other platforms produce different headers then
on say x86, I don't see this creating a problem or adding to
false-positive matches since COMMAND is also a invalid pid like PID is,
and thus it's more efficient to remove it in one check rather then two
independant case-select's.

 As for the rationale behind using 'ps -axwww ...' it's quite simple,
without it, it's impossible to match examples like qmail-smtpd above,
if the method I proposed fails to match any valid likelies in _arg0
then _argv is parsed by word matching against the same values as _arg0
was, producing a valid and relative match, using 'www' ensures that
full path is displayed, producing more text to match against for each
process being parsed.

>I strongly suggest ensuring that you're working with rc.subr from
>NetBSD-current, because I've made significant portability, performance
>and functionality enhancements to it since NetBSD 1.5.

 In this I agree that the case-select used in v1.30+ for both
check_process() and check_pidfile() is better then the if-then used in
the FreeBSD-current /etc/rc.subr (v1.28) and the NetBSD 1.5 /etc/rc.subr
(v1.20.2.4) for both functions.

>By the way, I'm going to be at USENIX next week talking about rc.d. If
>you (or any other FreeBSD developer who is going to be there) wants to
>chat about this stuff then, feel free to find me and bend my ear!
>
>Luke.

 It should be noted that I foolishly emailed Luke instead of keeping
this in -arch so I apologize to Luke (and those who got annoyed by me
doing this) for stepping on whatever and whomever's toes.

 I feel these are valid reasons for the various changes I've proposed
in order what I know will be a ongoing problem until a specialized tool
is written to handle this properly.

 David O'Brien also mentioned that some people might say that the two
extra pipes used in filtering out the unwanted data in the ps report
might slow things down (as NetBSD runs on some slow, older hardware) in
this I really can't say what the impact would be, again, lending itself
toward the creation of a tool which exists in /bin (thus should be OK
in all mounting suituations) that can pull the specific process id in
question. (There was some talk of this on IRC a while ago...)

- Chris


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010619012658.A53486>