Bug#734688: Logs are not rotated for a month - patch
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
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) {