-/* $Cambridge: exim/src/src/exim_lock.c,v 1.3 2005/06/27 14:29:43 ph10 Exp $ */
-
/* A program to lock a file exactly as Exim would, for investigation of
interlocking problems.
#define FIND_RUNNING_INTERFACES
#endif
+#ifndef OS_GET_DNS_RESOLVER_RES
+ #define OS_GET_DNS_RESOLVER_RES
+#endif
+
#include "../src/os.c"
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;
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];
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,
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 */
}
}
- 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",
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,
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