From 92b0959366a4677d8ac916cd9246a80853ae4765 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Mon, 17 Oct 2016 17:59:31 +0200
Subject: createOutputFile: eliminate stat/open TOCTOU race

---
 logrotate.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/logrotate.c b/logrotate.c
index e415164..c4b8e0c 100644
--- a/logrotate.c
+++ b/logrotate.c
@@ -394,11 +394,18 @@ static int runScript(struct logInfo *log, char *logfn, char *script)
 
 int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, int force_mode)
 {
-    int fd;
+    int fd = -1;
     struct stat sb_create;
     int acl_set = 0;
+    int i;
+
+    for (i = 0; i < 2; ++i) {
+	fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
+		(S_IRUSR | S_IWUSR) & sb->st_mode);
+
+	if ((fd >= 0) || (errno != EEXIST))
+	    break;
 
-    if (stat(fileName, &sb_create) == 0) {
 	/* the destination file already exists, while it should not */
 	struct tm now = *localtime(&nowSecs);
 	size_t fileName_size = strlen(fileName);
@@ -412,11 +419,9 @@ int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, i
 		    fileName, backupName, strerror(errno));
 	    return -1;
 	}
+	/* existing file renamed, try it once again */
     }
 
-	fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
-		(S_IRUSR | S_IWUSR) & sb->st_mode);
-
     if (fd < 0) {
 	message(MESS_ERROR, "error creating output file %s: %s\n",
 		fileName, strerror(errno));
-- 
2.7.4