diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-05-13 18:43:11 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-13 18:43:11 +0200 |
commit | 88136bbc9897f506e4b4de21378f523b6099cf41 (patch) | |
tree | c784a724998d5754df29e691e9a90a16562654ac | |
parent | Merge pull request #8959 from yuwata/bash-completion-analyze (diff) | |
parent | basic: add log_level argument to timezone_is_valid (diff) | |
download | systemd-88136bbc9897f506e4b4de21378f523b6099cf41.tar.xz systemd-88136bbc9897f506e4b4de21378f523b6099cf41.zip |
Merge pull request #8962 from floppym/issue8905
basic: timezone_is_valid: check for magic bytes "TZif"
-rw-r--r-- | src/basic/calendarspec.c | 2 | ||||
-rw-r--r-- | src/basic/time-util.c | 35 | ||||
-rw-r--r-- | src/basic/time-util.h | 2 | ||||
-rw-r--r-- | src/firstboot/firstboot.c | 8 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-lease.c | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-server.c | 2 | ||||
-rw-r--r-- | src/network/networkd-network.c | 2 | ||||
-rw-r--r-- | src/test/test-time-util.c | 8 | ||||
-rw-r--r-- | src/timedate/timedated.c | 2 |
9 files changed, 45 insertions, 18 deletions
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index 4cf21100cc..f8c798f31f 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -937,7 +937,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { const char *last_space; last_space = strrchr(p, ' '); - if (last_space != NULL && timezone_is_valid(last_space + 1)) { + if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) { c->timezone = strdup(last_space + 1); if (!c->timezone) return -ENOMEM; diff --git a/src/basic/time-util.c b/src/basic/time-util.c index fa7cda5d2c..5d278d42cb 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -21,11 +21,13 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "io-util.h" #include "log.h" #include "macro.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -875,7 +877,7 @@ int parse_timestamp(const char *t, usec_t *usec) { int r; last_space = strrchr(t, ' '); - if (last_space != NULL && timezone_is_valid(last_space + 1)) + if (last_space != NULL && timezone_is_valid(last_space + 1, LOG_DEBUG)) tz = last_space + 1; if (!tz || endswith_no_case(t, " UTC")) @@ -1273,10 +1275,12 @@ int get_timezones(char ***ret) { return 0; } -bool timezone_is_valid(const char *name) { +bool timezone_is_valid(const char *name, int log_level) { bool slash = false; const char *p, *t; - struct stat st; + _cleanup_close_ int fd = -1; + char buf[4]; + int r; if (isempty(name)) return false; @@ -1305,11 +1309,30 @@ bool timezone_is_valid(const char *name) { return false; t = strjoina("/usr/share/zoneinfo/", name); - if (stat(t, &st) < 0) + + fd = open(t, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + log_full_errno(log_level, errno, "Failed to open timezone file '%s': %m", t); + return false; + } + + r = fd_verify_regular(fd); + if (r < 0) { + log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t); return false; + } + + r = loop_read_exact(fd, buf, 4, false); + if (r < 0) { + log_full_errno(log_level, r, "Failed to read from timezone file '%s': %m", t); + return false; + } - if (!S_ISREG(st.st_mode)) + /* Magic from tzfile(5) */ + if (memcmp(buf, "TZif", 4) != 0) { + log_full(log_level, "Timezone file '%s' has wrong magic bytes", t); return false; + } return true; } @@ -1380,7 +1403,7 @@ int get_timezone(char **tz) { if (!e) return -EINVAL; - if (!timezone_is_valid(e)) + if (!timezone_is_valid(e, LOG_DEBUG)) return -EINVAL; z = strdup(e); diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 5b2674a4b6..e720688c2b 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -128,7 +128,7 @@ int parse_nsec(const char *t, nsec_t *nsec); bool ntp_synced(void); int get_timezones(char ***l); -bool timezone_is_valid(const char *name); +bool timezone_is_valid(const char *name, int log_level); bool clock_boottime_supported(void); bool clock_supported(clockid_t clock); diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index ce37339307..7895e3832a 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -364,6 +364,10 @@ static int process_keymap(void) { return 0; } +static bool timezone_is_valid_log_error(const char *name) { + return timezone_is_valid(name, LOG_ERR); +} + static int prompt_timezone(void) { _cleanup_strv_free_ char **zones = NULL; int r; @@ -387,7 +391,7 @@ static int prompt_timezone(void) { putchar('\n'); - r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid, &arg_timezone); + r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid_log_error, &arg_timezone); if (r < 0) return r; @@ -827,7 +831,7 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_TIMEZONE: - if (!timezone_is_valid(optarg)) { + if (!timezone_is_valid(optarg, LOG_ERR)) { log_error("Timezone %s is not valid.", optarg); return -EINVAL; } diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index ed951aeb7d..505d02b50d 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -667,7 +667,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void return 0; } - if (!timezone_is_valid(tz)) { + if (!timezone_is_valid(tz, LOG_DEBUG)) { log_debug_errno(r, "Timezone is not valid, ignoring: %m"); return 0; } diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 351b567423..d97bb9a075 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -1069,7 +1069,7 @@ int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *tz) { int r; assert_return(server, -EINVAL); - assert_return(timezone_is_valid(tz), -EINVAL); + assert_return(timezone_is_valid(tz, LOG_DEBUG), -EINVAL); if (streq_ptr(tz, server->timezone)) return 0; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index daa30cb8f0..2b03fc254b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -1012,7 +1012,7 @@ int config_parse_timezone( if (r < 0) return r; - if (!timezone_is_valid(tz)) { + if (!timezone_is_valid(tz, LOG_ERR)) { log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue); free(tz); return 0; diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c index 5393deff70..5b8e7c7b35 100644 --- a/src/test/test-time-util.c +++ b/src/test/test-time-util.c @@ -168,9 +168,9 @@ static void test_format_timespan(usec_t accuracy) { } static void test_timezone_is_valid(void) { - assert_se(timezone_is_valid("Europe/Berlin")); - assert_se(timezone_is_valid("Australia/Sydney")); - assert_se(!timezone_is_valid("Europe/Do not exist")); + assert_se(timezone_is_valid("Europe/Berlin", LOG_ERR)); + assert_se(timezone_is_valid("Australia/Sydney", LOG_ERR)); + assert_se(!timezone_is_valid("Europe/Do not exist", LOG_ERR)); } static void test_get_timezones(void) { @@ -182,7 +182,7 @@ static void test_get_timezones(void) { assert_se(r == 0); STRV_FOREACH(zone, zones) - assert_se(timezone_is_valid(*zone)); + assert_se(timezone_is_valid(*zone, LOG_ERR)); } static void test_usec_add(void) { diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 93810d43d3..6928bb9a97 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -542,7 +542,7 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error * if (r < 0) return r; - if (!timezone_is_valid(z)) + if (!timezone_is_valid(z, LOG_DEBUG)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid time zone '%s'", z); r = free_and_strdup(&c->zone, z); |