-/* $Cambridge: exim/src/src/exim_lock.c,v 1.1 2004/10/07 10:39:01 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"
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];
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 */
/* 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)
}
}
- 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;
}
- chmod (tempname, 0600);
+ /* 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,
lock_flock_timeout) >= 0)
struct stat strestore;
struct utimbuf ut;
stat(filename, &strestore);
- system(command);
+ i = system(command);
ut.actime = strestore.st_atime;
ut.modtime = strestore.st_mtime;
utime(filename, &ut);
}
-else 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