Blame SOURCES/logrotate-3.8.6-rename-existing.patch

6e9866
From def2d2aebad1a6d1b149780181943e0cafa63bdc Mon Sep 17 00:00:00 2001
6e9866
From: Mathieu Parent <Mathieu.PARENT@nantesmetropole.fr>
6e9866
Date: Tue, 8 Mar 2016 16:56:50 +0100
6e9866
Subject: [PATCH 1/3] createOutputFile: rename already existing file
6e9866
6e9866
See https://bugs.debian.org/734688
6e9866
6e9866
Closes #23
6e9866
6e9866
Upstream-commit: fc1c3eff61edf8e9f0a4bfa980f3a6030a6b271f
6e9866
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
6e9866
---
6e9866
 logrotate.c            | 20 ++++++++++++++++++--
6e9866
 test/test              | 26 ++++++++++++++++++++++++++
6e9866
 test/test-config.72.in |  7 +++++++
6e9866
 3 files changed, 51 insertions(+), 2 deletions(-)
6e9866
 create mode 100644 test/test-config.72.in
6e9866
6e9866
diff --git a/logrotate.c b/logrotate.c
6e9866
index f13d140..976210e 100644
6e9866
--- a/logrotate.c
6e9866
+++ b/logrotate.c
6e9866
@@ -395,8 +395,24 @@ static int runScript(struct logInfo *log, char *logfn, char *script)
6e9866
 int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, int force_mode)
6e9866
 {
6e9866
     int fd;
6e9866
-	struct stat sb_create;
6e9866
-	int acl_set = 0;
6e9866
+    struct stat sb_create;
6e9866
+    int acl_set = 0;
6e9866
+
6e9866
+    if (stat(fileName, &sb_create) == 0) {
6e9866
+	/* the destination file already exists, while it should not */
6e9866
+	struct tm now = *localtime(&nowSecs);
6e9866
+	size_t fileName_size = strlen(fileName);
6e9866
+	char* backupName = alloca(fileName_size + sizeof("-YYYYMMDDHH.backup"));
6e9866
+	strncpy(backupName, fileName, fileName_size);
6e9866
+	size_t date_size=strftime(backupName+fileName_size, 12, "-%Y%m%d%H", &now;;
6e9866
+	strncpy(backupName+fileName_size+date_size, ".backup\0", 8);
6e9866
+	message(MESS_ERROR, "destination %s already exists, renaming to %s\n", fileName, backupName);
6e9866
+	if (rename(fileName, backupName) != 0) {
6e9866
+	    message(MESS_ERROR, "error renaming already existing output file %s to %s: %s\n",
6e9866
+		    fileName, backupName, strerror(errno));
6e9866
+	    return -1;
6e9866
+	}
6e9866
+    }
6e9866
 
6e9866
 	fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
6e9866
 		(S_IRUSR | S_IWUSR) & sb->st_mode);
6e9866
diff --git a/test/test b/test/test
6e9866
index bcdfe05..b47ac6a 100755
6e9866
--- a/test/test
6e9866
+++ b/test/test
6e9866
@@ -1586,6 +1586,32 @@ EOF
6e9866
 rm -rf testdir adir
6e9866
 rm -rf testdir bdir
6e9866
 
6e9866
+cleanup 72
6e9866
+
6e9866
+# ------------------------------- Test 72 ------------------------------------
6e9866
+preptest test.log 72 2
6e9866
+
6e9866
+$RLR test-config.72 --force
6e9866
+
6e9866
+checkoutput <
6e9866
+test.log 0
6e9866
+test.log.1 0 zero
6e9866
+test.log.2.gz 1 first
6e9866
+EOF
6e9866
+
6e9866
+echo 'unexpected' > test.log.1.gz
6e9866
+
6e9866
+$RLR test-config.72 --force
6e9866
+dt="$(date +%Y%m%d%H)"
6e9866
+
6e9866
+checkoutput <
6e9866
+test.log 0
6e9866
+test.log.1 0
6e9866
+test.log.1.gz-$dt.backup 0 unexpected
6e9866
+test.log.2.gz 1 zero
6e9866
+test.log.3.gz 1 first
6e9866
+EOF
6e9866
+
6e9866
 cleanup 73
6e9866
 
6e9866
 # ------------------------------- Test 73 ------------------------------------
6e9866
diff --git a/test/test-config.72.in b/test/test-config.72.in
6e9866
new file mode 100644
6e9866
index 0000000..9fe50a2
6e9866
--- /dev/null
6e9866
+++ b/test/test-config.72.in
6e9866
@@ -0,0 +1,7 @@
6e9866
+&DIR&/test.log {
6e9866
+    daily
6e9866
+    rotate 3
6e9866
+    compress
6e9866
+    delaycompress
6e9866
+    create
6e9866
+}
6e9866
-- 
6e9866
2.17.2
6e9866
6e9866
6e9866
From 1fa3ff8477d3766f0cc39631ace8c63ee99a1974 Mon Sep 17 00:00:00 2001
6e9866
From: Kamil Dudka <kdudka@redhat.com>
6e9866
Date: Mon, 17 Oct 2016 17:59:31 +0200
6e9866
Subject: [PATCH 2/3] createOutputFile: eliminate stat/open TOCTOU race
6e9866
6e9866
Upstream-commit: aff4a30807218a52b6b5f200c5aa0eea335547ba
6e9866
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
6e9866
---
6e9866
 logrotate.c | 15 ++++++++++-----
6e9866
 1 file changed, 10 insertions(+), 5 deletions(-)
6e9866
6e9866
diff --git a/logrotate.c b/logrotate.c
6e9866
index 976210e..fdc81ac 100644
6e9866
--- a/logrotate.c
6e9866
+++ b/logrotate.c
6e9866
@@ -394,11 +394,18 @@ static int runScript(struct logInfo *log, char *logfn, char *script)
6e9866
 
6e9866
 int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, int force_mode)
6e9866
 {
6e9866
-    int fd;
6e9866
+    int fd = -1;
6e9866
     struct stat sb_create;
6e9866
     int acl_set = 0;
6e9866
+    int i;
6e9866
+
6e9866
+    for (i = 0; i < 2; ++i) {
6e9866
+	fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
6e9866
+		(S_IRUSR | S_IWUSR) & sb->st_mode);
6e9866
+
6e9866
+	if ((fd >= 0) || (errno != EEXIST))
6e9866
+	    break;
6e9866
 
6e9866
-    if (stat(fileName, &sb_create) == 0) {
6e9866
 	/* the destination file already exists, while it should not */
6e9866
 	struct tm now = *localtime(&nowSecs);
6e9866
 	size_t fileName_size = strlen(fileName);
6e9866
@@ -412,11 +419,9 @@ int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, i
6e9866
 		    fileName, backupName, strerror(errno));
6e9866
 	    return -1;
6e9866
 	}
6e9866
+	/* existing file renamed, try it once again */
6e9866
     }
6e9866
 
6e9866
-	fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
6e9866
-		(S_IRUSR | S_IWUSR) & sb->st_mode);
6e9866
-
6e9866
     if (fd < 0) {
6e9866
 	message(MESS_ERROR, "error creating output file %s: %s\n",
6e9866
 		fileName, strerror(errno));
6e9866
-- 
6e9866
2.20.1
6e9866
6e9866
6e9866
From 86d67f5769575104add7846b822069008c912b3c Mon Sep 17 00:00:00 2001
6e9866
From: Kamil Dudka <kdudka@redhat.com>
6e9866
Date: Mon, 17 Oct 2016 18:13:32 +0200
6e9866
Subject: [PATCH 3/3] createOutputFile: improve code readability
6e9866
6e9866
Upstream-commit: 5ecd908033a481c1e127ba583697d6662ffea4a3
6e9866
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
6e9866
---
6e9866
 logrotate.c | 24 +++++++++++++++++-------
6e9866
 1 file changed, 17 insertions(+), 7 deletions(-)
6e9866
6e9866
diff --git a/logrotate.c b/logrotate.c
6e9866
index fdc81ac..5b0df30 100644
6e9866
--- a/logrotate.c
6e9866
+++ b/logrotate.c
6e9866
@@ -409,14 +409,24 @@ int createOutputFile(char *fileName, int flags, struct stat *sb, acl_type acl, i
6e9866
 	/* the destination file already exists, while it should not */
6e9866
 	struct tm now = *localtime(&nowSecs);
6e9866
 	size_t fileName_size = strlen(fileName);
6e9866
-	char* backupName = alloca(fileName_size + sizeof("-YYYYMMDDHH.backup"));
6e9866
-	strncpy(backupName, fileName, fileName_size);
6e9866
-	size_t date_size=strftime(backupName+fileName_size, 12, "-%Y%m%d%H", &now;;
6e9866
-	strncpy(backupName+fileName_size+date_size, ".backup\0", 8);
6e9866
-	message(MESS_ERROR, "destination %s already exists, renaming to %s\n", fileName, backupName);
6e9866
+	size_t buf_size = fileName_size + sizeof("-YYYYMMDDHH.backup");
6e9866
+	char *backupName = alloca(buf_size);
6e9866
+	char *ptr = backupName;
6e9866
+
6e9866
+	/* construct backupName starting with fileName */
6e9866
+	strcpy(ptr, fileName);
6e9866
+	ptr += fileName_size;
6e9866
+	buf_size -= fileName_size;
6e9866
+
6e9866
+	/* append the -YYYYMMDDHH time stamp and the .backup suffix */
6e9866
+	ptr += strftime(ptr, buf_size, "-%Y%m%d%H", &now;;
6e9866
+	strcpy(ptr, ".backup");
6e9866
+
6e9866
+	message(MESS_ERROR, "destination %s already exists, renaming to %s\n",
6e9866
+		fileName, backupName);
6e9866
 	if (rename(fileName, backupName) != 0) {
6e9866
-	    message(MESS_ERROR, "error renaming already existing output file %s to %s: %s\n",
6e9866
-		    fileName, backupName, strerror(errno));
6e9866
+	    message(MESS_ERROR, "error renaming already existing output file"
6e9866
+		    " %s to %s: %s\n", fileName, backupName, strerror(errno));
6e9866
 	    return -1;
6e9866
 	}
6e9866
 	/* existing file renamed, try it once again */
6e9866
-- 
6e9866
2.20.1
6e9866