Bug#734688: Logs are not rotated for a month - patch

2014-02-26 Thread Bolesław Tokarski

I have just bumped myself to the same issue. Your error message:


error: error creating output file /var/log/syslog.1.gz: File exists


indicates that the file syslog.1.gz exists. @madduck can you check that the 
file doesn't really exist?

In my case a previous logrotate command must have been interrupted while 
gzipping, creating:
syslog
syslog.1
syslog.1.gz
syslog.2.gz
etc
where syslog.1.gz was of 0 size. Apparently, the compression error causes this 
to not attempt rename and rotation.

I suggest adding some handling to logrotate so that it would check the 
destination file's existance.
In the patch attached I am modifying the 'createOutputFile' function to stat 
the destination file and either
remove it (if it's of size 0) or rename it to .garbage (otherwise).

I have given very little testing to this patch, please reviewtest it.

--- logrotate-3.8.7.orig/logrotate.c
+++ logrotate-3.8.7/logrotate.c
@@ -300,10 +300,34 @@ static int runScript(struct logInfo *log
 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;

-   fd = open(fileName, (flags | O_EXCL | O_NOFOLLOW),
+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+fnlegth, garbage\0);
+ 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),
(S_IRUSR | S_IWUSR)  sb-st_mode);

 if (fd  0) {


Bug#734688: Logs are not rotated for a month - patch

2014-02-26 Thread Bolesław Tokarski
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) {