Package: logrotate
Version: 3.8.5-1
Severity: important
Tags: patch l10n upstream

Hi there,

we found a daylight saving time (DST) bug in logrotate. 
We want that our logfiles are rotated away once a year 
on January first, but only if they have grown larger than 1 MB.
Due to the bug in logrotate they get rotated twice a
year. First time on January first and a second time when they 
grow larger than 1 MB. This comes from a wrong conversion of 
the times stored in the status file. A example of the problem is:

   sh> export TZ="MEZ-1MSZ,M3.5.0,M10.5.0"
   sh> echo $TZ
   MEZ-1MSZ,M3.5.0,M10.5.0


   sh> date
   Tue Jul 30 10:46:03 MSZ 2013


   sh> cat /etc/logrotate.conf
   ...

   /tmp/logfile
   { yearly
     minsize 1M
   }

   ...


   sh> ls -lh /tmp/logfile
   -rw-rw-r-- 1 root root 39M Jul 30 10:40 /tmp/logfile


   sh> cat /var/lib/logrotate/status
   logrotate state -- version 2
   "/tmp/logfile" 2013-1-1-0:0:0


   sh> logrotate -d /etc/logrotate.conf
   rotating pattern: "/tmp/logfile"
    yearly (100 rotations)
   olddir is /var/log/alt, empty log files are not rotated,
    only log files >= 1048576 bytes are rotated, old logs are removed
   considering log /tmp/logfile
     log needs rotating
   rotating log /tmp/logfile, log->rotateCount is 100
   copying /tmp/logfile to /tmp/old/logfile-2013-07-29
   truncating /tmp/logfile


At        

logrotate.c:945:           state->lastRotated = now;

the "lastRotated" is initialized with the value of "now", which makes
no sense, since whatever date is found in the status file, it has
never anything to do with the actual date. However, due to this 
initialisation, in our testcase the the field "state->lastRotated.tm_isdst"
is set to 1, because DST is active at the time "now".

At
logrotate.c:2107:          st->lastRotated.tm_year = year;
logrotate.c:2108:          st->lastRotated.tm_mon = month;
logrotate.c:2109:          st->lastRotated.tm_mday = day;
logrotate.c:2110:          st->lastRotated.tm_hour = hour;
logrotate.c:2111:          st->lastRotated.tm_min = minute;
logrotate.c:2112:          st->lastRotated.tm_sec = second;
logrotate.c:2113:
logrotate.c:2114:          /* fill in the rest of the st->lastRotated fields */
logrotate.c:2115:          lr_time = mktime(&st->lastRotated);
logrotate.c:2116:          st->lastRotated = *localtime(&lr_time);

only the fields "tm_year", "tm_month", "tm_mday", "tm_hour", "tm_min"
and "tm_sec" are changed but not tm_isdst, so it is still set when the time
conversions in line 2115 and 2116 are done. The documentation for mkdoc says,
that if tm_isdst is 1 then the time conversion is done with enabled DST which
is wrong in our case for the time 2013-01-01T00:00:00. For that reason we find
in "st->lastRotated" after the conversion the time 2012-12-31T23:00:00 which
lies in the year 2012 and therefore logrotate thinks the logfile needs rotation.

Our solution for the problem (pobably not the best) is to initialize the
structur correctly by setting the "tm_isdst" field to -1. The documentation
of mkdoc states, that this uses the DST which has been or will be in effect at
the date converted, which is precisely what we want.

Patch:
--- a/logrotate.c
+++ b/logrotate.c
@@ -2104,12 +2104,14 @@ static int readState(char *stateFilename)
                return 1;
        }

+       memset (&st->lastRotated, 0, sizeof st->lastRotated);
        st->lastRotated.tm_year = year;
        st->lastRotated.tm_mon = month;
        st->lastRotated.tm_mday = day;
        st->lastRotated.tm_hour = hour;
        st->lastRotated.tm_min = minute;
        st->lastRotated.tm_sec = second;
+       st->lastRotated.tm_isdst = -1;

        /* fill in the rest of the st->lastRotated fields */
        lr_time = mktime(&st->lastRotated);


Probably one would also have a look at all the other uses of mkdoc.
There might be similar problems.

Best regards

Rüdiger

-- System Information:
Debian Release: jessie/sid
  APT prefers testing
  APT policy: (550, 'testing'), (500, 'stable'), (210, 'unstable'), (1, 
'experimental')
Architecture: i386 (x86_64)

Kernel: Linux 3.11.0-rc3-64+ (SMP w/16 CPU cores; PREEMPT)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash

Versions of packages logrotate depends on:
ii  base-passwd         3.5.26
ii  cron [cron-daemon]  3.0pl1-124
ii  libacl1             2.2.52-1
ii  libc6               2.17-7
ii  libpopt0            1.16-7
ii  libselinux1         2.1.13-2

Versions of packages logrotate recommends:
ii  heirloom-mailx [mailx]  12.5-2

logrotate suggests no packages.

-- Configuration Files:
/etc/logrotate.conf changed [not included]

-- no debconf information


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to