From fee5c52ac260d021466c1062499f0ebd5241db5f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 18:16:25 +0200 Subject: [PATCH 1/4] stat-util: add stat_inode_unmodified() helper that checks if an inode was modified --- src/basic/stat-util.c | 21 +++++++++++++++++++++ src/basic/stat-util.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 1f3de56cf9..e4e4d8f076 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -388,3 +388,24 @@ int proc_mounted(void) { return r; } + +bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { + + /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to + * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file + * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file + * size, backing device, inode type and if this refers to a device not the major/minor. + * + * Note that we don't care if file attributes such as ownership or access mode change, this here is + * about contents of the file. The purpose here is to detect file contents changes, and nothing + * else. */ + + return a && b && + (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ + ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ + a->st_mtime == b->st_mtime && + (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ + a->st_dev == b->st_dev && + a->st_ino == b->st_ino && + (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ +} diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 8160748312..59aedcb7c4 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -89,3 +89,5 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret); int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno); int proc_mounted(void); + +bool stat_inode_unmodified(const struct stat *a, const struct stat *b); From 61c12865f5653e34521d3bbf7c667cd4ea5f7385 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 18:16:47 +0200 Subject: [PATCH 2/4] resolved: port to stat_inode_unmodified() --- src/resolve/resolved-manager.h | 4 +++- src/resolve/resolved-resolv-conf.c | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index cbad1dce60..cbaef5e49c 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include + #include "sd-event.h" #include "sd-netlink.h" #include "sd-network.h" @@ -71,7 +73,7 @@ struct Manager { bool need_builtin_fallbacks:1; bool read_resolv_conf:1; - usec_t resolv_conf_mtime; + struct stat resolv_conf_stat; DnsTrustAnchor trust_anchor; diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index c06213f486..97aee7abc8 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -14,6 +14,7 @@ #include "resolved-conf.h" #include "resolved-dns-server.h" #include "resolved-resolv-conf.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "tmpfile-util-label.h" @@ -93,7 +94,7 @@ int manager_read_resolv_conf(Manager *m) { } /* Have we already seen the file? */ - if (timespec_load(&st.st_mtim) == m->resolv_conf_mtime) + if (stat_inode_unmodified(&st, &m->resolv_conf_stat)) return 0; if (file_is_our_own(&st)) @@ -159,7 +160,7 @@ int manager_read_resolv_conf(Manager *m) { log_syntax(NULL, LOG_DEBUG, "/etc/resolv.conf", n, 0, "Ignoring resolv.conf line: %s", l); } - m->resolv_conf_mtime = timespec_load(&st.st_mtim); + m->resolv_conf_stat = st; /* Flush out all servers and search domains that are still * marked. Those are then ones that didn't appear in the new From 491ce161037a11b52abec74eeb6c8cfa512ef1fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 17:04:08 +0200 Subject: [PATCH 3/4] sd-bus: introduce new SD_BUS_VTABLE_ABSOLUTE_OFFSET vtable flag When set, the offset specified for the vtable entry is passed to the handler as-is, and is not added to the userdata pointer. This is useful in case methods/properties are mixed on the same vtable, that expect to operate relative to some object in memory and that expect pointers to absolute memory, or that just want a number passed. --- src/libsystemd/sd-bus/bus-objects.c | 4 ++-- src/systemd/sd-bus-vtable.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c index ad66d634d7..6abac8822c 100644 --- a/src/libsystemd/sd-bus/bus-objects.c +++ b/src/libsystemd/sd-bus/bus-objects.c @@ -56,7 +56,7 @@ static int node_vtable_get_userdata( static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); - if (!u) + if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET)) return SIZE_TO_PTR(p->x.method.offset); /* don't add offset on NULL, to make ubsan happy */ return (uint8_t*) u + p->x.method.offset; @@ -65,7 +65,7 @@ static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) { static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) { assert(p); - if (!u) + if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET)) return SIZE_TO_PTR(p->x.property.offset); /* as above */ return (uint8_t*) u + p->x.property.offset; diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h index f2423ba456..b10a3e04bc 100644 --- a/src/systemd/sd-bus-vtable.h +++ b/src/systemd/sd-bus-vtable.h @@ -44,6 +44,7 @@ enum { SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6, SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7, SD_BUS_VTABLE_SENSITIVE = 1ULL << 8, /* covers both directions: method call + reply */ + SD_BUS_VTABLE_ABSOLUTE_OFFSET = 1ULL << 9, _SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40 }; From 0271e9b10c71c26f7b33a6141278b71d55b89626 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2020 19:23:50 +0200 Subject: [PATCH 4/4] man: complete vtable flag documentation --- man/sd_bus_add_object.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/man/sd_bus_add_object.xml b/man/sd_bus_add_object.xml index 60f04187f8..102ee66d29 100644 --- a/man/sd_bus_add_object.xml +++ b/man/sd_bus_add_object.xml @@ -544,6 +544,25 @@ This corresponds to the org.freedesktop.systemd1.Explicit annotation in introspection data. + + + SD_BUS_VTABLE_SENSITIVE + + Mark this vtable method entry as processing sensitive data. When set, + incoming method call messages and their outgoing reply messages are marked as sensitive using + sd_bus_message_sensitive3, + so that they are erased from memory when freed. + + + + SD_BUS_VTABLE_ABSOLUTE_OFFSET + + Mark this vtable method or property entry so that the user data pointer passed to + its associated handler functions is determined slightly differently: instead of adding the offset + parameter of the entry to the user data pointer specified during vtable registration, the offset is + passed directly, converted to a pointer, without taking the user data pointer specified during + vtable registration into account. +