X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ff790e47f2de6f4d6d48148e1d5a67da8e93c446..43ba2742c700d625dcdcdaf7bbadc2f72776854a:/src/src/exim_lock.c diff --git a/src/src/exim_lock.c b/src/src/exim_lock.c index 9b5b26209..37d974477 100644 --- a/src/src/exim_lock.c +++ b/src/src/exim_lock.c @@ -1,5 +1,3 @@ -/* $Cambridge: exim/src/src/exim_lock.c,v 1.2 2005/06/22 15:44:38 ph10 Exp $ */ - /* A program to lock a file exactly as Exim would, for investigation of interlocking problems. @@ -72,6 +70,10 @@ the other stuff in os.c, so force the other macros to omit it. */ #define FIND_RUNNING_INTERFACES #endif +#ifndef OS_GET_DNS_RESOLVER_RES + #define OS_GET_DNS_RESOLVER_RES +#endif + #include "../src/os.c" @@ -173,7 +175,7 @@ int fd = -1; int hd = -1; int md = -1; int yield = 0; -int now = time(NULL); +time_t now = time(NULL); BOOL use_lockfile = FALSE; BOOL use_fcntl = FALSE; BOOL use_flock = FALSE; @@ -183,7 +185,8 @@ BOOL quiet = FALSE; BOOL restore_times = FALSE; char *filename; char *lockname = NULL, *hitchname = NULL; -char *primary_hostname, *command; +char *primary_hostname; +const char *command; struct utsname s; char buffer[256]; char tempname[256]; @@ -297,8 +300,10 @@ if (use_lockfile) lockname = malloc(len + 8); sprintf(lockname, "%s.lock", filename); hitchname = malloc(len + 32 + (int)strlen(primary_hostname)); + + /* Presumably, this must match appendfile.c */ sprintf(hitchname, "%s.%s.%08x.%08x", lockname, primary_hostname, - now, (int)getpid()); + (unsigned int)now, (unsigned int)getpid()); if (verbose) printf("exim_lock: lockname = %s\n hitchname = %s\n", lockname, @@ -310,7 +315,8 @@ if (use_lockfile) for (j = 0; j < lock_retries; j++) { int sleep_before_retry = TRUE; - struct stat statbuf, ostatbuf; + struct stat statbuf, ostatbuf, lstatbuf, statbuf2; + int mbx_tmp_oflags; /* Try to build a lock file if so configured */ @@ -329,7 +335,7 @@ for (j = 0; j < lock_retries; j++) /* Apply hitching post algorithm. */ if ((rc = link(hitchname, lockname)) != 0) fstat(hd, &statbuf); - close(hd); + (void)close(hd); unlink(hitchname); if (rc != 0 && statbuf.st_nlink != 2) @@ -431,7 +437,11 @@ for (j = 0; j < lock_retries; j++) } } - md = open(tempname, O_RDWR | O_CREAT, 0600); + mbx_tmp_oflags = O_RDWR | O_CREAT; +#ifdef O_NOFOLLOW + mbx_tmp_oflags |= O_NOFOLLOW; +#endif + md = open(tempname, mbx_tmp_oflags, 0600); if (md < 0) { printf("exim_lock: failed to create mbx lock file %s: %s\n", @@ -439,6 +449,30 @@ for (j = 0; j < lock_retries; j++) goto CLEAN_UP; } + /* security fixes from 2010-05 */ + if (lstat(tempname, &lstatbuf) < 0) + { + printf("exim_lock: failed to lstat(%s) after opening it: %s\n", + tempname, strerror(errno)); + goto CLEAN_UP; + } + if (fstat(md, &statbuf2) < 0) + { + printf("exim_lock: failed to fstat() open fd of \"%s\": %s\n", + tempname, strerror(errno)); + goto CLEAN_UP; + } + if ((statbuf2.st_nlink > 1) || + (lstatbuf.st_nlink > 1) || + (!S_ISREG(lstatbuf.st_mode)) || + (lstatbuf.st_dev != statbuf2.st_dev) || + (lstatbuf.st_ino != statbuf2.st_ino)) + { + printf("exim_lock: race condition exploited against us when " + "locking \"%s\"\n", tempname); + goto CLEAN_UP; + } + (void)chmod(tempname, 0600); if (apply_lock(md, F_WRLCK, use_fcntl, lock_fcntl_timeout, use_flock, @@ -551,12 +585,14 @@ if (restore_times) struct stat strestore; struct utimbuf ut; stat(filename, &strestore); - (void)system(command); + i = system(command); ut.actime = strestore.st_atime; ut.modtime = strestore.st_mtime; utime(filename, &ut); } -else (void)system(command); +else i = system(command); + +if(i && !quiet) printf("warning: nonzero status %d\n", i); /* Remove the locks and exit. Unlink the /tmp file if we can get an exclusive lock on the mailbox. This should be a non-blocking lock call, as there is no