sendmail bug (and fix)
Jeff Stearns
jeff at fluke.UUCP
Sat Dec 10 09:36:28 AEST 1983
Subject: sendmail can trash its alias database
Index: usr.lib/sendmail 4.2BSD
Description:
If the sendmail alias database is out of date, two concurrent
invocations of sendmail could each begin to update it in parallel.
The resultant database may be garbaged.
Repeat-By:
The following procedure is slightly non-deterministic, but it has
been effective for us in provoking the problem 50% of the time:
Configure /usr/lib/sendmail.cf for automatic database rebuilding:
# rebuild alias database if out-of-date:
OD
Create /usr/lib/aliases.{dir,pag}
% touch /usr/lib/aliases.
% mail root </dev/null &
% mail root </dev/null &
Now the tricky part -- test for bad aliases. A short C program using
the dbm(3) routines may be helpful.
Fix:
----- /usr/src/usr.lib/sendmail/alias.c -----
1a2
> # include <sys/file.h>
155a157
> int aliaslock;
218a221,256
> **
> ** FLUKE jps 28-sept-83 - Modified to provide some file locking
> ** on the alias database:
> **
> ** We have observed that concurrent sendmail's will rebuild
> ** the database in parallel, leading to trashed .{dir,pag} files.
> ** This code seeks to prevent that by using file locking as a
> ** semaphore.
> **
> ** Ideally we would like to lock the dbm version of the
> ** database - either the .dir or .pag file (or both).
> ** The database routines should always open the .pag file
> ** with an advisory lock, which would be upgraded to an
> ** exclusive one while the database is being updated.
> ** Unfortunately that's difficult because the file is opened
> ** by dbminit and we never see the file descriptor. We could
> ** open it a second time ourself solely for locking purposes,
> ** but there's an alternative. We lock the unencoded alias
> ** file instead. If you think about it, it really doesn't
> ** matter *what* file we lock, so long as all instantiations
> ** of sendmail agree upon it (and we retain the convention of
> ** having a distinguished alias for "@").
> **
> ** Note that we open the alias file here solely for the purposes
> ** of hanging a lock around it. Within readaliases() it will
> ** be opened a second time for actual processing. I did it this
> ** way to minimize the amount of modified code.
> **
> ** Note also that this code could be better written to save
> ** sequential updatings. As it is, several concurrent sendmails
> ** could each see the need for rebuilding the database, and each
> ** will do so, but now they'll do it sequentially, not in parallel.
> ** With a bit more smarts, we could prevent that, but it's not
> ** worth the bother to save *work*. We're trying to prevent
> ** trashed alias files.
> **
222a261,263
> if(((aliaslock = open(aliasfile, O_RDONLY)) < 0) ||
> flock(aliaslock, LOCK_EX) < 0)
> syserr("can't lock alias file for rebuilding");
256a298
> (void) close(aliaslock);
Jeff Stearns, John Fluke Mfg. Co., Inc.
P.O. Box C9090, Everett WA 98043
...!decvax!microsoft!fluke!jeff
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list