Red Hat Bugzilla – Bug 217317
localtime() doesn't cache /etc/localtime contents, gets confused following chroot()
Last modified: 2007-11-30 17:11:50 EST
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
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):
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.)
Sun Nov 26 23:54:44 2006
Sun Nov 26 16:54:44 2006
Created attachment 142142 [details]
Sample test program.
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.
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