I did some basic testing and investigations and I am attaching a corrected patch.

I have found that the problem only started appearing in version 3.8.0. In versions prior to that, the security-388608.patch used an unlink(fileName) in the beginning of createOutputFile function call.

However, in debian/changelog it is mentioned that the security bug that this patch was related to was fixed upstream. I don't know how it was fixed, but the unlink was gone and the O_EXCL flag in the createOutputFile is set in fopen causing the call to fail when the destination file exists.


diff --git a/logrotate.c b/logrotate.c
index 174a26b..1306b1f 100644
--- a/logrotate.c
+++ b/logrotate.c
@@ -300,10 +300,35 @@ 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;
-       struct stat sb_create;
-       int acl_set = 0;
+    struct stat sb_create;
+    int acl_set = 0;
+
+    if (stat(fileName, &sb_create) == 0) {
+       /* this indicates that the destination file exists, while it should not */
+       if (sb_create.st_size == 0) {
+         /* the file is of zero size, so not needed */
+         if (unlink(fileName) != 0) {
+           message(MESS_ERROR, "output file %s exists and failed to remove it: %s\n",
+                  fileName, strerror(errno));
+           return -1;
+         }
+       } else {
+         int fnlength=sizeof(fileName);
+         char* garbage=malloc(fnlength+8); /* 'garbage\0' */
+         strncpy(garbage, fileName, fnlength);
+         strncpy(garbage+fnlength, "garbage\0", 8);
+         if (rename(fileName,garbage) != 0) {
+           message(MESS_ERROR, "output file %s exists and failed to rename it to %s: %s\n",
+                  fileName, garbage, strerror(errno));
+           free(garbage);
+           return -1;
+       }
+       free(garbage);
+
+      }
+    }
 
-       fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
+    fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
                (S_IRUSR | S_IWUSR) & sb->st_mode);
 
     if (fd < 0) {

Reply via email to