[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [leafnode-list] lockfile_exists disaster, analysis of 1.9.19 and
Matthias Andree wrote:
> ----------------------------------------------------------------------
> ANALYSIS OF 1.9.19 RACE
> ----------------------------------------------------------------------
>
> 1.9.19 has a TOC-TOU race (time of check - time of use). If a context
> switch occurs between the read-open and the write-open of the lock file,
> two processes can have the lock, since both of them have seen "no lock
> file there" (or possibly "removed stale lock file"), and fopen(...,"w")
> does not set O_EXCL on open(2). Non-atomicity issue here.
Here is what I believe to be a fix. Patch your version of 1.9.19 with it:
--- miscutil.c.orig Tue Jun 5 17:36:13 2001
+++ miscutil.c Wed Jun 13 17:18:17 2001
@@ -115,44 +115,65 @@
* also return 1, otherwise return 0
*/
int lockfile_exists( void ) {
- FILE * lf ;
- int pid ;
+ int fd;
+ FILE *lf;
+ int pid;
+ char *lockfilename;
- if ( ( lf = fopen( lockfile, "r+" )) != NULL ) {
- if ( fscanf( lf, "%d", &pid ) ) {
+ /* obtain a unique lockfile name, consisting of lockfile + pid */
+ lockfilename = critmalloc(strlen(lockfile)+10,
+ "Allocating space for lockfile name");
+ snprintf(lockfilename, strlen(lockfile)+9, "%s-%d", lockfile, getpid());
+ if ((fd = open(lockfilename, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) {
+ syslog(LOG_ERR, "Creating unique lockfile failed: %m");
+ return 1; /* behave like a lockfile would exist */
+ }
+ close(fd);
+
+ /* try to obtain exclusive control over the lockfile */
+ if (link(lockfilename, lockfile) < 0) {
+ /* lockfile already exists. Does the process still exist as well? */
+ lf = fopen(lockfile, "r+");
+ if (lf == NULL) {
+ syslog(LOG_ERR, "Cannot open old lockfile: %m");
+ unlink(lockfilename);
+ return 1; /* lockfile exists */
+ }
+ if (fscanf(lf, "%d", &pid)) {
fclose( lf );
- if ( kill( pid, 0 ) == -1 && errno == ESRCH ) {
+ if ( kill(pid, 0) == -1 && errno == ESRCH ) {
if ( verbose )
- printf( "Removing stale lockfile.\n" );
- syslog( LOG_INFO, "Removing stale lockfile: pid %d", pid );
- unlink( lockfile );
+ printf( "Lockfile is stale, ignoring.\n" );
+ syslog( LOG_INFO, "Ignoring stale lockfile: pid %d", pid );
} else {
printf( "lockfile %s exists, abort ...\n", lockfile);
syslog( LOG_ERR, "lockfile %s exists, abort ...",
lockfile);
+ unlink(lockfilename);
return 1;
}
} else {
- fclose( lf );
- syslog( LOG_ERR, "unable to read lockfile %s, abort ...", lockfile );
+ fclose(lf);
+ syslog(LOG_ERR, "unable to read lockfile %s, abort ...", lockfile);
+ unlink(lockfilename);
return 1;
}
- } else if ( errno != ENOENT ) {
- syslog( LOG_ERR, "unable to open lockfile %s: %d %m", lockfile, errno );
}
- if ( ( lf = fopen( lockfile, "w" )) != NULL ) {
+
+ /* We have obtained the exclusive lock. Write pid into it. */
+ if ( (lf = fopen( lockfile, "w" )) != NULL ) {
fprintf( lf, "%d", (int)getpid() );
- fclose( lf );
+ fclose(lf);
+ unlink(lockfilename);
return 0;
} else {
- printf( "Could not open lockfile %s for writing, abort program ...\n",
- lockfile );
- syslog( LOG_ERR, "Could not open lockfile %s for writing: %m",
- lockfile );
+ printf("Could not open lockfile %s for writing, abort program ...\n",
+ lockfile);
+ syslog(LOG_ERR, "Could not open lockfile %s for writing: %m", lockfile);
+ unlink(lockfilename);
return 1;
}
}
-
/*
* check whether "groupname" is represented in interesting.groups without
I don't have tcpserver, but maybe somebody else can try out whether this
version of lockfile_exists() is safe. I put this version into my local
2.0b tree right now and will soon find out whether there are any problems
with it :-/
--Cornelius.
--
/* Cornelius Krasel, U Wuerzburg, Dept. of Pharmacology, Versbacher Str. 9 */
/* D-97078 Wuerzburg, Germany email: krasel@xxxxxxxxxxxxxxxxxxxxxxxxxxxx */
/* "Science is the game we play with God to find out what His rules are." */
--
leafnode-list@xxxxxxxxxxxxxxxxxxxxxxxxxxxx -- mailing list for leafnode
To unsubscribe, send mail with "unsubscribe" in the subject to the list