Date: Sat, 27 Sep 2025 17:07:37 GMT From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= <des@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: df8bc705eb04 - main - tzcode: Fix issues when TZ is an absolute path Message-ID: <202509271707.58RH7bUq091024@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=df8bc705eb04aff2f718678fffb9d5d4f5d7c223 commit df8bc705eb04aff2f718678fffb9d5d4f5d7c223 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2025-09-27 17:07:04 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2025-09-27 17:07:16 +0000 tzcode: Fix issues when TZ is an absolute path * If TZ starts with TZDIR, strip any additional slashes so relname does not end up looking like an absolute path. For instance, TZ=/usr/share/zoneinfo//UTC should result in UTC, not /UTC. * In the setugid case, we were incorrectly passing name rather than relname to fstatat(). * Modify the tz_env and tz_env_setugid test cases to exercise both of these scenarios. * Also add test cases for invalid values of TZ, which I wrote earlier but forgot to include in a5f14e4f9069. Reported by: Paul Eggert <eggert@cs.ucla.edu> MFC after: 3 days Fixes: 967a49a21a27 ("Update tzcode to 2025b") Fixes: a5f14e4f9069 ("tzcode: Use -00 only for invalid time zones") Reviewed by: philip Differential Revision: https://reviews.freebsd.org/D52753 --- lib/libc/gen/sysconf.c | 2 +- lib/libc/tests/stdtime/Makefile | 1 + lib/libc/tests/stdtime/detect_tz_changes_test.c | 90 ++++++++++++++++++++++--- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c index 66562d0e29f0..b5b732eed05d 100644 --- a/lib/libc/gen/sysconf.c +++ b/lib/libc/gen/sysconf.c @@ -51,7 +51,7 @@ #include "un-namespace.h" #include "../stdlib/atexit.h" -#include "tzdir.h" /* from ../../../contrib/tzcode/stdtime */ +#include "tzdir.h" /* from ../../../contrib/tzcode */ #include "libc_private.h" #define _PATH_ZONEINFO TZDIR /* from tzfile.h */ diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile index 6b9068e1641b..590dea22da31 100644 --- a/lib/libc/tests/stdtime/Makefile +++ b/lib/libc/tests/stdtime/Makefile @@ -3,6 +3,7 @@ ATF_TESTS_C+= strptime_test ATF_TESTS_C+= detect_tz_changes_test +CFLAGS.detect_tz_changes_test+= -I${SRCTOP}/contrib/tzcode .if ${MK_DETECT_TZ_CHANGES} != "no" CFLAGS.detect_tz_changes_test+= -DDETECT_TZ_CHANGES .endif diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c index 6648d8498cc5..fe6b04357331 100644 --- a/lib/libc/tests/stdtime/detect_tz_changes_test.c +++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c @@ -20,6 +20,8 @@ #include <time.h> #include <unistd.h> +#include "tzdir.h" + #include <atf-c.h> static const struct tzcase { @@ -62,9 +64,9 @@ debug(const char *fmt, ...) static void change_tz(const char *tzn) { - static const char *zfn = "/usr/share/zoneinfo"; - static const char *tfn = "root/etc/.localtime"; - static const char *dfn = "root/etc/localtime"; + static const char *zfn = TZDIR; + static const char *tfn = "root" TZDEFAULT ".tmp"; + static const char *dfn = "root" TZDEFAULT; ssize_t clen; int zfd, sfd, dfd; @@ -96,6 +98,50 @@ test_tz(const char *expect) ATF_CHECK_STREQ(expect, buf); } +ATF_TC(tz_default); +ATF_TC_HEAD(tz_default, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test default zone"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_default, tc) +{ + /* prepare chroot with no /etc/localtime */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* check timezone */ + unsetenv("TZ"); + test_tz("+0000 (UTC)"); +} + +ATF_TC(tz_invalid_file); +ATF_TC_HEAD(tz_invalid_file, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test invalid zone file"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_invalid_file, tc) +{ + static const char *dfn = "root/etc/localtime"; + int fd; + + /* prepare chroot with bogus /etc/localtime */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + ATF_REQUIRE((fd = open(dfn, O_RDWR | O_CREAT, 0644)) >= 0); + ATF_REQUIRE_EQ(8, write(fd, "invalid\n", 8)); + ATF_REQUIRE_EQ(0, close(fd)); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* check timezone */ + unsetenv("TZ"); + test_tz("+0000 (-00)"); +} + ATF_TC(thin_jail); ATF_TC_HEAD(thin_jail, tc) { @@ -327,10 +373,38 @@ ATF_TC_HEAD(tz_env, tc) } ATF_TC_BODY(tz_env, tc) { - const struct tzcase *tzcase; + char path[MAXPATHLEN]; + const struct tzcase *tzcase = tzcases; + int len; + /* relative path */ for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) test_tz_env(tzcase->tzfn, tzcase->expect); + /* absolute path */ + for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) { + len = snprintf(path, sizeof(path), "%s/%s", TZDIR, tzcase->tzfn); + ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path)); + test_tz_env(path, tzcase->expect); + } + /* absolute path with additional slashes */ + for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) { + len = snprintf(path, sizeof(path), "%s/////%s", TZDIR, tzcase->tzfn); + ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path)); + test_tz_env(path, tzcase->expect); + } +} + + +ATF_TC(tz_invalid_env); +ATF_TC_HEAD(tz_invalid_env, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test invalid TZ value"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_invalid_env, tc) +{ + test_tz_env("invalid", "+0000 (-00)"); + test_tz_env(":invalid", "+0000 (-00)"); } ATF_TC(setugid); @@ -367,23 +441,23 @@ ATF_TC_HEAD(tz_env_setugid, tc) } ATF_TC_BODY(tz_env_setugid, tc) { - const struct tzcase *tzcase = tzcases; - ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY)); ATF_REQUIRE(issetugid()); - for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) - test_tz_env(tzcase->tzfn, tzcase->expect); + ATF_TC_BODY_NAME(tz_env)(tc); } ATF_TP_ADD_TCS(tp) { debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") && isatty(STDERR_FILENO); + ATF_TP_ADD_TC(tp, tz_default); + ATF_TP_ADD_TC(tp, tz_invalid_file); ATF_TP_ADD_TC(tp, thin_jail); #ifdef DETECT_TZ_CHANGES ATF_TP_ADD_TC(tp, detect_tz_changes); #endif /* DETECT_TZ_CHANGES */ ATF_TP_ADD_TC(tp, tz_env); + ATF_TP_ADD_TC(tp, tz_invalid_env); ATF_TP_ADD_TC(tp, setugid); ATF_TP_ADD_TC(tp, tz_env_setugid); return (atf_no_error());
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509271707.58RH7bUq091024>