tobold.org

correct • elegant • free

△ comp.unix.shell △

◅ grep behaves differently in find

exit code ▻

Passwd/Shadow conflict access control

In article <85g2rq$8c5$2@news-int.gatech.edu>,
Jehsom <jehsom@-NOSPAM-resnet.gatech.edu> wrote:
> if [ -f /etc/passwd.lock ]; then
>  echo "/etc/passwd is in use by another process. Please try again later."
>  exit 1
> else
>  touch /etc/passwd.lock
>  vi /etc/passwd
>  rm /etc/passwd.lock
> fi

Several problems here.  The first is that vipw uses /etc/ptmp as its
lock file (at least on BSD-like systems).  Therefore you have no locking
with respect to vipw.

The second is that editing the password file in place is a really bad
idea.  (Consider what happens if another process attempts to access the
file just as vi starts to rewrite it.)  You should do what vipw does:
edit a copy of the file, then atomically rename (`mv') it into place.

The third is that you have a race condition.  Two simultaneous
invocations of this script could both find that the lock file doesn't
exist, and go on to create it.  To avoid the race, you need an atomic
test-and-lock primitive.  Shell scripts don't have ready acccess to such
a primitive for lock *files* (C programs can use O_EXCL), but you can
use a lock *directory* instead: two `mkdir's can't both succeed.

Here's a script (mildly tested) which fixes the second and third
problems.  It still doesn't interact safely with vipw, though.

    lockdir=/var/run/passwd-lock

    mkdir "$lockdir" || exit 1
    trap 'rm -f "$lockdir"' 0 1 2 15

    cp /etc/passwd /etc/ptmp || exit 1
    vi /etc/ptmp && mv /etc/ptmp /etc/passwd

When I needed to do this recently (because I won't use NIS, and
Digital had an attack of Not Invented Here when they came to do shadow
passwords), I used Perl.  The relevant parts of the script follow.

    #! /usr/local/bin/perl -w

    use Fcntl;

    # Lock the password file.
    sysopen PTMP, "/etc/ptmp", O_WRONLY | O_CREAT | O_EXCL or
            die "$0: can't open /etc/ptmp for output: $!\n";

    ...  # Create the new password file in /etc/ptmp

    close PTMP or die "$0: close of /etc/ptmp failed: $!\n";

    # Move the new password file into place.
    rename "/etc/ptmp", "/etc/passwd" or
            die "$0: rename /etc/ptmp to /etc/passwd failed: $!\n";

Tim.
--
Tim Goodwin   | "If you don't know what closures are, you probably don't
Leicester, UK | want to know what closures are." -- Larry Wall

Original headers:

From: tjg@star.le.ac.uk (Tim Goodwin)
Newsgroups: comp.unix.shell
Subject: Re: Passwd/Shadow conflict access control
Date: 12 Jan 2000 14:49:36 -0000
Message-ID: <85i4am$47i$1@ltpcg.star.le.ac.uk>
References: <387B8A13.D42CF213@embratel.net.br>
  <85g2rq$8c5$2@news-int.gatech.edu>

△ comp.unix.shell △

◅ grep behaves differently in find

exit code ▻