diff options
author | Giedrius Statkevičius <giedriuswork@gmail.com> | 2020-03-22 22:40:18 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2020-04-17 12:27:10 +0200 |
commit | 9c61b53c748f024add63fa78b940449f48d965d9 (patch) | |
tree | 5f99b4d31d131c6d1e2afa78b328f9688c2cd370 | |
parent | d540b947f41d6690dd99aaab533846ac1c673da7 (diff) | |
download | systemd-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.c | 9 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 2 | ||||
-rw-r--r-- | src/resolve/resolved-manager.h | 2 |
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 */ |