Load the time zone and connect syslog before chroot

The C library reads /etc/localtime on the first use of local time and
connects to /dev/log on the first syslog() call. With a chroot before
either, every local time became UTC and every syslog message was lost.
The time zone is now loaded before chroot() and openlog() connects at
once. The chroot entry of 3proxy.cfg(5) lists what PAM, LDAP and ODBC
still need inside the chroot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Vladimir Dubrovin 2026-10-12 18:16:22 +03:00
parent c14393cfe4
commit f1b8d30799
2 changed files with 18 additions and 2 deletions

View File

@ -1388,7 +1388,12 @@ for all threads.
.BR chroot
\fI<path>\fR [\fI<uid>\fR] [\fI<gid>\fR]
.br
calls chroot(path) and sets gid/uid. Unix only. uid/gid supported since 0.9, can be numeric or username/groupname
calls chroot(path) and sets gid/uid. Unix only. uid/gid supported since 0.9, can be numeric or username/groupname.
The time zone and the syslog connection are set up before the call.
Plugins which read their own configuration or load modules while running need them inside the chroot:
PAM (\fI/etc/pam.d\fR and the modules it names, read for every authentication),
LDAP (\fIldap.conf\fR and, for ldaps, the CA certificates),
ODBC (\fIodbc.ini\fR, \fIodbcinst.ini\fR and the driver libraries, loaded again whenever the connection is reopened).
.br
.BR stacksize

View File

@ -378,7 +378,8 @@ static int h_log(int argc, unsigned char ** argv){
#ifndef _WIN32
conf.logfunc = logsyslog;
if(notchanged) return 0;
openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON);
/* connected now: after a chroot there is no /dev/log to find */
openlog((char *)conf.logtarget+1, LOG_PID | LOG_NDELAY, LOG_DAEMON);
#endif
}
#ifdef WITH_ODBC
@ -1921,6 +1922,14 @@ static int h_setgid(int argc, unsigned char **argv){
}
/* What the C library reads on first use from files a chroot hides, read
while they can still be found: the time zone, without which every time
is UTC. Names looked up through the system cannot be helped this way, the
hosts file and resolv.conf are read again for lookups to come. */
static void prechroot(void){
tzset();
}
static int h_chroot(int argc, unsigned char **argv){
uid_t uid = 0;
gid_t gid = 0;
@ -1940,6 +1949,8 @@ static int h_chroot(int argc, unsigned char **argv){
}
if(!chrootp){
char *p;
prechroot();
if(chroot((char *)argv[1])) {
fprintf(stderr, "Unable to chroot %s", argv[1]);
return(1);