summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiedrius Statkevičius <giedriuswork@gmail.com>2020-03-22 22:40:18 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-04-17 12:27:10 +0200
commit9c61b53c748f024add63fa78b940449f48d965d9 (patch)
tree5f99b4d31d131c6d1e2afa78b328f9688c2cd370
parentd540b947f41d6690dd99aaab533846ac1c673da7 (diff)
downloadsystemd-9c61b53c748f024add63fa78b940449f48d965d9.tar.gz
resolve: reload /etc/hosts on inode change
On certain distributions such as NixOS the mtime of `/etc/hosts` is locked to a fixed value. In such cases, only checking the last mtime of `/etc/hosts` is not enough - we also need to check if the st_ino/st_dev match up. Thus, let's make sure make sure that systemd-resolved also rereads `/etc/hosts` if the inode or the device containing `/etc/hosts` changes. Test script: ```bash hosts="/etc/hosts" echo "127.0.0.1 testpr" > "hosts_new" mv "hosts_new" "$hosts" resolvectl query testpr || exit 1 mtime="$(stat -c %y "$hosts")" echo "127.0.0.1 newhost" > "hosts_tmp" touch -d "$mtime" "hosts_tmp" install -p "hosts_tmp" "$hosts" sleep 10 resolvectl query newhost || exit 1 rm -f "hosts_tmp" ``` Closes #14456. (cherry picked from commit aa5408e2e8a66b71f38531f1dcb91252c586a23c)
-rw-r--r--src/resolve/resolved-etc-hosts.c9
-rw-r--r--src/resolve/resolved-manager.c2
-rw-r--r--src/resolve/resolved-manager.h2
3 files changed, 11 insertions, 2 deletions
diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c
index e6bf20db54..c2839d425a 100644
--- a/src/resolve/resolved-etc-hosts.c
+++ b/src/resolve/resolved-etc-hosts.c
@@ -37,6 +37,8 @@ void etc_hosts_free(EtcHosts *hosts) {
void manager_etc_hosts_flush(Manager *m) {
etc_hosts_free(&m->etc_hosts);
m->etc_hosts_mtime = USEC_INFINITY;
+ m->etc_hosts_ino = 0;
+ m->etc_hosts_dev = 0;
}
static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
@@ -224,8 +226,9 @@ static int manager_etc_hosts_read(Manager *m) {
return 0;
}
- /* Did the mtime change? If not, there's no point in re-reading the file. */
- if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime)
+ /* Did the mtime or ino/dev change? If not, there's no point in re-reading the file. */
+ if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime &&
+ st.st_ino == m->etc_hosts_ino && st.st_dev == m->etc_hosts_dev)
return 0;
}
@@ -249,6 +252,8 @@ static int manager_etc_hosts_read(Manager *m) {
return r;
m->etc_hosts_mtime = timespec_load(&st.st_mtim);
+ m->etc_hosts_ino = st.st_ino;
+ m->etc_hosts_dev = st.st_dev;
m->etc_hosts_last = ts;
return 1;
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 4f72077720..df25907a4c 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -591,6 +591,8 @@ int manager_new(Manager **ret) {
.need_builtin_fallbacks = true,
.etc_hosts_last = USEC_INFINITY,
.etc_hosts_mtime = USEC_INFINITY,
+ .etc_hosts_ino = 0,
+ .etc_hosts_dev = 0,
.read_etc_hosts = true,
};
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 7f7d3a6b9c..446f258b49 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -127,6 +127,8 @@ struct Manager {
/* Data from /etc/hosts */
EtcHosts etc_hosts;
usec_t etc_hosts_last, etc_hosts_mtime;
+ ino_t etc_hosts_ino;
+ dev_t etc_hosts_dev;
bool read_etc_hosts;
/* Local DNS stub on 127.0.0.53:53 */