From 16eff8271b402f2705d4329fa4cf5a0435e65996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jun 2021 15:40:27 +0200 Subject: [PATCH 1/4] tmpfiles: stop complaining about autofs on not-found paths systemd-tmpfiles[328]: Failed to determine whether '/run/cryptsetup' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/etc/resolv.conf' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/lock/subsys' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/setrans' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/console' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/faillock' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/sepermit' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/motd.d' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/motd.d' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/motd' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/run/nologin' is below autofs, ignoring: No such file or directory systemd-tmpfiles[328]: Failed to determine whether '/var/lib/systemd/pstore' is below autofs, ignoring: No such file or directory ... and so on and so on. --- src/tmpfiles/tmpfiles.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 071070e9f6..032673f08d 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2354,7 +2354,7 @@ static int process_item(Item *i, OperationMask operation) { i->done |= operation; - r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL); + r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL); if (r == -EREMOTE) { log_notice_errno(r, "Skipping %s", i->path); return 0; From 1e472a6ce4747a1f10954fb239df73580c8e7411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jun 2021 16:01:40 +0200 Subject: [PATCH 2/4] basic/glob-util: add helper to strip the glob part from a glob --- src/basic/glob-util.c | 19 +++++++++++++++++++ src/basic/glob-util.h | 2 ++ src/test/test-glob-util.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c index bc0278e57f..e026b29478 100644 --- a/src/basic/glob-util.c +++ b/src/basic/glob-util.c @@ -71,3 +71,22 @@ int glob_extend(char ***strv, const char *path, int flags) { return strv_extend_strv(strv, g.gl_pathv, false); } + +int glob_non_glob_prefix(const char *path, char **ret) { + /* Return the path of the path that has no glob characters. */ + + size_t n = strcspn(path, GLOB_CHARS); + + if (path[n] != '\0') + while (n > 0 && path[n-1] != '/') + n--; + + if (n == 0) + return -ENOENT; + + char *ans = strndup(path, n); + if (!ans) + return -ENOMEM; + *ret = ans; + return 0; +} diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h index d2f8718d5a..fc86e990dd 100644 --- a/src/basic/glob-util.h +++ b/src/basic/glob-util.h @@ -13,6 +13,8 @@ int safe_glob(const char *path, int flags, glob_t *pglob); int glob_exists(const char *path); int glob_extend(char ***strv, const char *path, int flags); +int glob_non_glob_prefix(const char *path, char **ret); + #define _cleanup_globfree_ _cleanup_(globfree) _pure_ static inline bool string_is_glob(const char *p) { diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c index df6444c433..50b4924679 100644 --- a/src/test/test-glob-util.c +++ b/src/test/test-glob-util.c @@ -13,6 +13,8 @@ #include "tmpfile-util.h" static void test_glob_exists(void) { + log_info("/* %s */", __func__); + char name[] = "/tmp/test-glob_exists.XXXXXX"; int fd = -1; int r; @@ -48,6 +50,8 @@ static void test_glob_no_dot(void) { int r; + log_info("/* %s */", __func__); + assert_se(mkdtemp(template)); fn = strjoina(template, "/*"); @@ -68,6 +72,8 @@ static void test_safe_glob(void) { _cleanup_globfree_ glob_t g = {}; int r; + log_info("/* %s */", __func__); + assert_se(mkdtemp(template)); fn = strjoina(template, "/*"); @@ -93,10 +99,32 @@ static void test_safe_glob(void) { (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); } +static void test_glob_non_glob_prefix_one(const char *path, const char *expected) { + _cleanup_free_ char *t; + + assert_se(glob_non_glob_prefix(path, &t) == 0); + assert_se(streq(t, expected)); +} + +static void test_glob_non_glob(void) { + log_info("/* %s */", __func__); + + test_glob_non_glob_prefix_one("/tmp/.X11-*", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp/*", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp*", "/"); + test_glob_non_glob_prefix_one("/tmp/*/whatever", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp/*/whatever?", "/tmp/"); + test_glob_non_glob_prefix_one("/?", "/"); + + char *x; + assert_se(glob_non_glob_prefix("?", &x) == -ENOENT); +} + int main(void) { test_glob_exists(); test_glob_no_dot(); test_safe_glob(); + test_glob_non_glob(); return 0; } From bd6d28f21ad212e141b5e74bd0b7ad517f64a711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jun 2021 15:44:29 +0200 Subject: [PATCH 3/4] tmpfiles: do not check if unresolved globs are autofs paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the previous commit, we would not complain about the not-found path, but the check is still not useful. We use a libc function to resolve the glob, and it has no notion of treating autofs specially. So we can't avoid touching autofs when resolving globs. But usually the glob is found in the last component of the path, so if we strip the glob part, we can still do a useful check in many cases. (E.g. if /var/tmp is on autofs, something like "/var/tmp/" is much more likely than "/var//".) With the system config in F34, we check the following prefixes: /var/tmp/abrt/* → /var/tmp/abrt/ /run/log/journal/08a5690a2eed47cf92ac0a5d2e3cf6b0/*.journal* → /run/log/journal/08a5690a2eed47cf92ac0a5d2e3cf6b0/ /var/lib/systemd/coredump/.#core*.21e5c6c28c5747e6a4c7c28af9560a3d* → /var/lib/systemd/coredump/ /tmp/podman-run-* → /tmp/ /tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-*/tmp → /tmp/ /tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-* → /tmp/ /tmp/containers-user-* → /tmp/ /var/tmp/beakerlib-* → /var/tmp/ /var/tmp/dnf*/locks/* → /var/tmp/ /var/tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-*/tmp → /var/tmp/ /var/tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-* → /var/tmp/ /var/tmp/abrt/* → /var/tmp/abrt/ /var/tmp/beakerlib-* → /var/tmp/ /var/tmp/dnf*/locks/* → /var/tmp/ /tmp/podman-run-* → /tmp/ /tmp/containers-user-* → /tmp/ /tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-* → /tmp/ /tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-*/tmp → /tmp/ /var/tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-* → /var/tmp/ /var/tmp/systemd-private-21e5c6c28c5747e6a4c7c28af9560a3d-*/tmp → /var/tmp/ /var/lib/systemd/coredump/.#core*.21e5c6c28c5747e6a4c7c28af9560a3d* → /var/lib/systemd/coredump/ /run/log/journal/08a5690a2eed47cf92ac0a5d2e3cf6b0/*.journal* → /run/log/journal/08a5690a2eed47cf92ac0a5d2e3cf6b0/ --- src/tmpfiles/tmpfiles.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 032673f08d..45cd549029 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2344,6 +2344,8 @@ static int clean_item(Item *i) { static int process_item(Item *i, OperationMask operation) { OperationMask todo; + _cleanup_free_ char *_path = NULL; + const char *path; int r, q, p; assert(i); @@ -2354,9 +2356,21 @@ static int process_item(Item *i, OperationMask operation) { i->done |= operation; - r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL); + path = i->path; + if (string_is_glob(path)) { + /* We can't easily check whether a glob matches any autofs path, so let's do the check only + * for the non-glob part. */ + + r = glob_non_glob_prefix(path, &_path); + if (r < 0 && r != -ENOENT) + return log_debug_errno(r, "Failed to deglob path: %m"); + if (r >= 0) + path = _path; + } + + r = chase_symlinks(path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL); if (r == -EREMOTE) { - log_notice_errno(r, "Skipping %s", i->path); + log_notice_errno(r, "Skipping %s", i->path); /* We log the configured path, to not confuse the user. */ return 0; } if (r < 0) From ba405b220051d78c24e14dd30acdb1c6113aae28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 2 Jun 2021 16:32:36 +0200 Subject: [PATCH 4/4] TODO: coalesce entries for tmpfiles --- TODO | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 084a8540b3..ea626821a5 100644 --- a/TODO +++ b/TODO @@ -709,9 +709,6 @@ Features: * add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1 and so on, which would mean we could report errors and such. -* teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 - project quota - * introduce DefaultSlice= or so in system.conf that allows changing where we place our units by default, i.e. change system.slice to something else. Similar, ManagerSlice= should exist so that PID1's own scope unit could @@ -1330,6 +1327,8 @@ Features: should not follow symlinks. None of the other adjustment or creation calls follow symlinks. - add --test mode + - teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 + project quota * make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early