summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-05-13 18:43:11 +0200
committerGitHub <noreply@github.com>2018-05-13 18:43:11 +0200
commit88136bbc9897f506e4b4de21378f523b6099cf41 (patch)
treec784a724998d5754df29e691e9a90a16562654ac
parentMerge pull request #8959 from yuwata/bash-completion-analyze (diff)
parentbasic: add log_level argument to timezone_is_valid (diff)
downloadsystemd-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.c2
-rw-r--r--src/basic/time-util.c35
-rw-r--r--src/basic/time-util.h2
-rw-r--r--src/firstboot/firstboot.c8
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c2
-rw-r--r--src/network/networkd-network.c2
-rw-r--r--src/test/test-time-util.c8
-rw-r--r--src/timedate/timedated.c2
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);