Bug 217317

Summary: localtime() doesn't cache /etc/localtime contents, gets confused following chroot()
Product: [Fedora] Fedora Reporter: Philip Prindeville <philipp>
Component: glibcAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: Brian Brock <bbrock>
Severity: medium Docs Contact:
Priority: medium    
Version: 5CC: drepper
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2006-11-27 09:52:58 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Sample test program. none

Description Philip Prindeville 2006-11-27 00:01:47 UTC
Description of problem:

In gssftpd (part of the krb5-workstation) RPM does a chroot() when an anonymous
login session is started. However, the logs it writes (the file is opened
previous to the chroot()) gets written with timestamps (from ctime() in
ftpd.c:dolog()).

The problem is that all logs after the chroot() get written as GMT, since
ctime() no longer has access to the contents of /etc/localtime.

At a minimum, either a hook to prefect and store the contents of /etc/localtime
could be added, or else the man page could be explain the interaction of
chroot() with ctime(), and the importance of calling ctime() to prime its state
before the chroot().

Version-Release number of selected component (if applicable):

2.4-11

How reproducible:

Compile and run the attached file.  If compiled with -DBEFORE, it works
properly.  If compiled without it, it doesn't.  (Note: must be run as root
because of the chroot() in it.)
  
Actual results:

Sun Nov 26 23:54:44 2006


Expected results:

Sun Nov 26 16:54:44 2006


Additional info:

Comment 1 Philip Prindeville 2006-11-27 00:01:48 UTC
Created attachment 142142 [details]
Sample test program.

Comment 2 Jakub Jelinek 2006-11-27 09:52:58 UTC
Most of this is documented already in POSIX.
The "hook to prefetch /etc/localtime" is called tzset(3p), then there are several
functions which just use the timezone data (these do effectively an tzset only
if it hasn't been called yet in the current process, ctime is one of them) and
then other function where their 3p section man pages mention that they behave
as if they use tzset internally (e.g. localtime, these functions really do that).

If TZ env var is unset, tzset stats /etc/localtime and if it was called the
first time or if it changed since last call (this was added so that
changing timezone on a running system is possible without restarting everything),
it is reread (and if /etc/localtime is not valid, the default is TZ=GMT).

So, when using the chroot, preferrably link or bind mount /etc/localtime into
the chroot (e.g. system-config-date and /usr/sbin/tzdata-update copy
/etc/localtime over to /var/spool/postfix/etc/localtime if it existed previously
and had the same content as /etc/localtime), or tzset () before chrooting and
make sure you don't use any functions where documentation says it behaves as if
tzset () was called.

Comment 3 Philip Prindeville 2006-12-01 01:35:17 UTC
Ok, does localtime_r() behave like localtime() in this respect?

Does ctime_r() behave local ctime()?

And does openlog() call tzset() to make itself chroot()-safe?  If not, it might
be worth changing it so that it does.

But I guess the more important issue, is that when it is called repeatedly (as
happens in glibc's syslog() -- since it calls localtime_r() and strftime_r()),
should it be idempotent?  If you call it outside the chroot() prison, and
tzset() succeeds, then you chroot() and call it again and it fails to find its
files... should failing cause it to clobber the previously good results it had
from before?

Seems self-defeating.