From b5e9459d64bf7e109e1e0e48408c0352bbca3792 Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Mon, 12 Oct 2026 18:16:22 +0300 Subject: [PATCH] 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 --- man/3proxy.cfg.5 | 7 ++++++- src/conf.c | 13 ++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/man/3proxy.cfg.5 b/man/3proxy.cfg.5 index c6819a4..884965a 100644 --- a/man/3proxy.cfg.5 +++ b/man/3proxy.cfg.5 @@ -1388,7 +1388,12 @@ for all threads. .BR chroot \fI\fR [\fI\fR] [\fI\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 diff --git a/src/conf.c b/src/conf.c index bf5f769..bd14548 100644 --- a/src/conf.c +++ b/src/conf.c @@ -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);