[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

passwd file locking (was Re: New!!!: Base-passwd 2.0)



Behan Webster:
> The only thing that changes is that in step 3 they do a hard link
> from /etc/passwd to /etc/ptmp and then unlink /etc/ptmp.  (Effectively
> a rename.  I suspect that a rename isn't guaranteed atomic in linux?)

I'm pretty sure that rename() is atomic.  If implemented using link()
and unlink() - it isn't (and /etc/passwd will disappear if the process
is killed at precisely the right moment).

> I would suggest using this same locking mechanism and even making sure
> all debian utils that deal with /etc/passwd uses this same mechanism.

This mechanism, used in the early days of UN*X, has one problem that would
be nice to avoid: if the process dies before removing /etc/ptmp, this file
has to be removed manually before users can change their passwords again
(or even log in, if the password has just expired and must be changed).
(In real life: the sysadmin gets many phone calls from users who can't
change their passwords...)

Many newer systems (HP-UX 10.x, Solaris, SCO, ...) use a different locking
mechanism, specified by SVID.  There are two new libc functions: lckpwdf()
and ulckpwdf().  lckpwdf() blocks waiting to get the lock, returns 0 on
success and -1 on failure.  It fails if it can't get the lock within 15
seconds.  When you're done with your passwd file changes, call ulckpwdf()
to release the lock.

This nicely hides implementation details.  These functions are actually
implemented by using a POSIX (fcntl) lock on the file /etc/.pwd.lock (it's
in /etc because the files we are going to modify are in /etc too, and /var
might not even be mounted at the moment).  This way, the lock is always
released automatically (by the kernel) when the process exits.

The lckpwdf() and ulckpwdf() functions are present in libc-5.3.5 and newer
and in recent versions of glibc.  Now that we are using 5.4.20, I think we
can start modifying programs to use these functions.  Does anyone see any
problems with this?  (Note: I'm no perl expert.  How does one call standard
C library functions from perl scripts?  Anyway, adduser should ideally be
modified to run useradd to do all the dirty work...)

I plan to modify the shadow suite to use lckpwdf() soon.  Currently, it
uses a different locking mechanism (more reliable than /etc/ptmp, but
more complex as well).  It creates a temporary file (/etc/passwd.<pid>),
writes current pid to it, link("/etc/passwd.<pid>", "/etc/passwd.lock").
It then checks the link count (should work over NFS, too).  Any invalid
lock file is removed on next lock attempt if the process that created
the lock no longer exists (the lock file contains the pid).

BTW, I wonder why it has been decided to use the *.lock convention for
locking mailboxes.  It has similar problems as /etc/ptmp - if the lock
file is there after a crash, the user won't receive any mail.  Also,
MUAs need to be setgid mail to be able to create the lock.  Why not just
use fcntl() locks instead?  No special privileges required, and no more
problems with stale lock files...

Marek


--
TO UNSUBSCRIBE FROM THIS MAILING LIST: e-mail the word "unsubscribe" to
debian-devel-REQUEST@lists.debian.org . Trouble? e-mail to Bruce@Pixar.com


Reply to: