Bug 676254

Summary: vsftpd/ Timestamp problem
Product: Red Hat Enterprise Linux 5 Reporter: ritz <rkhadgar>
Component: vsftpdAssignee: Jiri Skala <jskala>
Status: CLOSED ERRATA QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: medium Docs Contact:
Priority: medium    
Version: 5.6CC: aglotov, dapospis, jwest, ovasik
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: vsftpd-2.0.5-21.el5 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2011-05-25 08:37:10 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Attachments:
Description Flags
patch fixing this issue mhlavink: review+

Description ritz 2011-02-09 08:37:03 UTC
Description of problem:
timestamps are printed incorrectly

1. File uploaded during DST hours.

    Example timezone of the server was set to  Europe/Amsterdam
    Time on the server was 21 Sep 2010 07:00 CEST [DST hour's for this timezone]
  
    File is uploaded on the server at 21 Sep @ 07:01

    Example 
    -rw-r--r--. 1 rrajaram rrajaram  841 Sep 21 07:01 vgdisplay


2.  DST period is over and the current system time is Tue Jan 18 06:59:09 CET 2011

3.  vsftpd has the following configuration

     use_localtime=YES/NO

      use_localtime if set to no(default), it sets to use GMT timezone instead of the localtime zone
      use_localtime if set to yes, it uses the system timezone


4. observer the time difference shown in both the cases from the client side after login [Server controls the timestamp]

     lsoutput taken from the server
     -rw-r--r-- 1 rrajaram rrajaram 841 Sep 21 07:01 vgdisplay
   

     VSFTPD configured with use_localtime=no [System is currently out of DST period]
     -rw-r--r--    1 500      500           841 Sep 21 05:01 vgdisplay


     VSFTPD configured with use_localtime=yes [System is currently out of DST period]
     -rw-r--r--    1 500      500           841 Sep 21 06:01 vgdisplay


      In above output, I believe second one is correct. vsftpd checks whether the file was uploaded during DST hour's and adjust the timestamp according to it

      in the aove first output, when vsftpd uses GMT timezone, difference is 2 hours. Is this correct behavior. Is logic wrong

      vsftpd just checks whether the file was uploaded during DST hour's and compares with the current GMT and says two hours difference


How reproducible:
always


Additional info:

Central European Standard Time = GMT+1
Central European Summer Time = GMT+2

gmtime works fine. the time returned by localtime seems to be the issue. 
localtime returned by ls ( from vsftpd) and by ls are different even after a service restart.

from ./sysutil.c

1340 const char*                                                                   
1341 vsf_sysutil_statbuf_get_date(const struct vsf_sysutil_statbuf* p_statbuf,     
1342                              int use_localtime)                               
1343 {                                                                             
...
1350   if (!use_localtime)                                                         
1351   {                                                                           
1352     p_tm = gmtime(&p_stat->st_mtime);                                         
1353   }                                                                           
1354   else                                                                        
1355   {                                                                           
1356     p_tm = localtime(&p_stat->st_mtime);                                      
1357   }                                                                           
...
1364   retval = strftime(datebuf, sizeof(datebuf), p_date_format, p_tm);           


from ./sysutil.c

2515 void                                                                                              
2516 vsf_sysutil_tzset(void)
2517 {
2518   int retval;                                                                                     
2519   char tzbuf[sizeof("+HHMM!")];                                                                   
2520   time_t the_time = time(NULL);                                                                   
2521   struct tm* p_tm;                                                                                
2522   tzset();
2523   p_tm = localtime(&the_time);                                                                    
2524   if (p_tm == NULL)                                                                               
2525   {
2526     die("localtime");                                                                             
2527   }
2528   /* Set our timezone in the TZ environment variable to cater for the fact                        
2529    * that modern glibc does not cache /etc/localtime (which becomes inaccessible                  
2530    * when we chroot().                                                                            
2531    */                                                                                             
2532   retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm);                                            
2533   tzbuf[sizeof(tzbuf) - 1] = '\0';
2534   if (retval == 5)      
2535   {                     
2536     /* Static because putenv() does not copy the string. */                                       
2537     static char envtz[sizeof("TZ=UTC-hh:mm")];
2538     /* Insert a colon so we have e.g. -05:00 instead of -0500 */                                  
2539     tzbuf[5] = tzbuf[4];                                                                          
2540     tzbuf[4] = tzbuf[3];
2541     tzbuf[3] = ':';
2542     /* Invert the sign - we just got the offset _from_ UTC but for TZ, we need                    
2543      * the offset _to_ UTC.                                                                       
2544      */
2545     if (tzbuf[0] == '+')                                                                          
2546     {
2547       tzbuf[0] = '-';                                                                             
2548     }
2549     else
2550     {
2551       tzbuf[0] = '+';
2552     }
2553     snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf);                                            
2554     putenv(envtz);
<--- We set up the TZ based on UTC, as we have no access to "/etc/localtime" under chroot environment 
<--- this leads to bad mojo

2555     s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60;                            
2556     s_timezone += ((tzbuf[4] - '0') * 10 + (tzbuf[5] - '0')) * 60;                                
2557     if (tzbuf[0] == '-')                                                                          
2558     {                                                                                             
2559       s_timezone *= -1;                                                                           
2560     }                                                                                             
2561   }
2562 }
2563

Comment 1 Jiri Skala 2011-02-15 14:47:21 UTC
(In reply to comment #0)
> 2553     snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf);                     
> 2554     putenv(envtz);
> <--- We set up the TZ based on UTC, as we have no access to "/etc/localtime"
> under chroot environment 
> <--- this leads to bad mojo
> 
That's right. TZ environmental variable affects results of localtime(). Mtime that is out of current DST state is corrupted.

Comment 8 Jiri Skala 2011-03-28 11:40:11 UTC
Created attachment 488131 [details]
patch fixing this issue

Vsftpd currently fills TZ environmental variable without DST specification. This leads to incorrect interpretation mtime value of the files that were last modified before latest DST change.
This patch uses content of /etc/localtime to fill up TZ inclusive DST definition.

Comment 12 errata-xmlrpc 2011-05-25 08:37:10 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on therefore solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHBA-2011-0830.html