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

Re: password file locking

Cooper wrote:
> Michael Tokarev wrote:
> >
> > But wait -- one big issue with this exists.  Note that
> > "dotlock" file created before opening real /etc/passwd file,
> > and it does _not_ removed after use. But applications that
> > updates /etc/passwd need to have reliable way to change
> > contents of that file, that is typically implemented by
> > creating new file and issuing two rename()s.
> I feel I'm starting to lose track here, so am I right in assuming you
> rename passwd to something else (passwd.old) and then the new thing to
> the new passwd?


> > With this,
> > it is hard to ensure that second app that waits for a lock
> > will use correct /etc/passwd when first lock released, not
> > a file that was renamed by first app.
> Correct. Which I think is exactly why you shouldn't use a second file
> when you try to lock a file. When you rename a new file to the current
> name, anybody who has the current file open will basically be using old
> data once the rename is complete. If that old data was used as a
> starting point for a modification the fun can begin.

Now I'm loosing the point... :)
This issue has nothing about locking.  There are two separate issues
  1.  How to prevent simultaneous write access to the same file(s)
  2.  How to tell applications that file was modified.

It seemed to be only one solution on 2 -- to rename cur -> old,
new -> cur (that two renames), and let apps to use old one until
they noticied the change (or, until bugs in them will be corrected).
If you update file inplace, things may get more complicated, when
app that have opened file that is updated will read from it next
time, it can get partial record or try to read from past of eof
etc.  Note _partial_ records -- this will be complete garbage,
it is worse than using old data.  Moreother, for most apps old
data is not an issue here at all -- consider `ls' for example --
it does not matter if it will show incorrect user name in it's
output.  Applications that deal with auth usually deal with
auth-data-files more carefully.

> > With this, "dotlock" method is far more reliable when
> > locking of /etc/passwd itself (recall -- dotlock _never_
> > removed).  Method used by util-linux (?) (creating
> > passwd.lck and shadow.lck) is less reliable, but
> > lckpwdf()'s one (creating /etc/.pwd.lock) is a best.
> I totally fail to see the apparently obvious advantage of having a lock
> file with a different name.
> When using a lock on the file itself, you're in the clear unless you
> want to replace the file in question with a different file. Since a file
> needs to be opened *BEFORE* you can acquire a POSIX lock, you need to
> stick to that one file which can be considered a disadvantage.
> If you want to add to the passwd file the POSIX lock will do. You lock,
> append, if that fails ftruncate back to the old size and it seems as if
> nothing happened.
> If you want to delete from the passwd file, you could use a POSIX lock.
> You lock, read, delete the line from the read data, write the data back
> to the file starting at filepos 0 and truncate whatever space is left.
> Problems arise when you want to update a line. It can be done with a
> POSIX lock too, but is more complicated. You lock, read, take out but
> locally store the line, write the remainder starting at pos 0, update
> the locally stored line in another location, write that at the current
> position of the file and if that were to fail you truncate back to that
> position and write the old line instead.
> This approach will work as long as nobody pulls the plug on the machine
> during the writes, which is really the only drawback of this approach.

This IS a point.  User's database is very sensitive data, if you
lost it, you will not be able to login/use your system.
Renames is more-or-less quick operation, compared to series of
read/writes on potentially big files.  Two renames still dangerous,
especially if we will be interrupted between 'em.  But I think
that it is better than read/writes.

> If that were to happen (enter Mr. Murphy) the potential is that lines
> get clobbered and that is, particularly with these files, totally
> unacceptable.
> To counter this the update and delete could simply blank out the line in
> the file and in the case of an update simply append to the end of the
> file. This will make a mess of the passwd file though.
> Bottom line, considering all this above (hope you'll excuse my
> think-as-I-type message) POSIX locks alone seem inadequate for this
> application.
> Still curious to see how the "dotlock" file thing solves the problem...
> Best I can tell it moves the problem to the lockfile, but doesn't remove
> it...

No, this approach completely solves problem with reliablity of
locking.  Only locking, not with other parts (potential lost/corruption
or using old data by some apps).  Let's see:

  1 we open /etc/.pwd.lock file with O_CREAT flag set, so it will be
  created if it doesn't exists.  It _never_ removed after (only

  2 we try to lock this file, and possible wait if it is already locked,
  using fcntl/flock/etc (what mechanism used on given machine)

  3 if we acquired the lock, we will open /etc/passwd (/etc/shadow etc),
  create /etc/npasswd with new info, rename passwd => opasswd,
  rename npasswd => passwd

  4 and only then we release lock on .pwd.lock.

If we will use lock on /etc/passwd itself, then on step 2, after
waiting for releasing other app's lock, we will have trouble
ensuring that we use correct /etc/password, not renamed by that
other app one.  This point always contains some timeslice where
race condition exists.  .pwd.lock file _never_ removed, so it is 
always the same -- no need to reopen/stat it after some other app
released it's lock on it.  We does not move the problem to another
place (file), we solve problem this way.

Creating files like /etc/shadow.lck and /etc/passwd.lck is a bit
better than locking /etc/passwd itself (using O_CREAT|O_EXCL),
but we should deal with stale locks and remove() that again
will cause the same things -- race condition exists here too.

> Cooper

Excuse me please for my not-so-good English -- I fell that I
just can't tell you all the story -- I just don't know _how_
to do this in English... :(((


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