From f1b8d30799dc348d6c647fc38910a777c4aa962f 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 77850bb..c3e0954 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 8ca5b53..6e09a25 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);