From bec890e3cd6dac249cb12ce9430fdb78b6cf546b Mon Sep 17 00:00:00 2001 From: Masahiro Matsuya Date: Wed, 31 Mar 2021 11:44:24 +0900 Subject: [PATCH 1/4] tmpfiles: use a entry in hashmap as ItemArray in read_config_file() [zjs: squash commits and use size_t as appropriate. Bug seems to have been introduced in 811a15877825da9e53f9a2a8603da34589af6bbb. Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1944468.] --- src/tmpfiles/tmpfiles.c | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index f11b4eed7c..df2b90e88f 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -3186,7 +3186,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe _cleanup_fclose_ FILE *_f = NULL; unsigned v = 0; FILE *f; - Item *i; + ItemArray *ia; int r = 0; assert(fn); @@ -3239,32 +3239,37 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe } /* we have to determine age parameter for each entry of type X */ - ORDERED_HASHMAP_FOREACH(i, globs) { - Item *j, *candidate_item = NULL; + ORDERED_HASHMAP_FOREACH(ia, globs) + for (size_t ni = 0; ni < ia->n_items; ni++) { + ItemArray *ja; + Item *i = ia->items + ni, *candidate_item = NULL; - if (i->type != IGNORE_DIRECTORY_PATH) - continue; - - ORDERED_HASHMAP_FOREACH(j, items) { - if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) + if (i->type != IGNORE_DIRECTORY_PATH) continue; - if (path_equal(j->path, i->path)) { - candidate_item = j; - break; + ORDERED_HASHMAP_FOREACH(ja, items) + for (size_t nj = 0; nj < ja->n_items; nj++) { + Item *j = ja->items + nj; + + if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) + continue; + + if (path_equal(j->path, i->path)) { + candidate_item = j; + break; + } + + if ((!candidate_item && path_startswith(i->path, j->path)) || + (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0))) + candidate_item = j; + } + + if (candidate_item && candidate_item->age_set) { + i->age = candidate_item->age; + i->age_set = true; } - - if ((!candidate_item && path_startswith(i->path, j->path)) || - (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0))) - candidate_item = j; } - if (candidate_item && candidate_item->age_set) { - i->age = candidate_item->age; - i->age_set = true; - } - } - if (ferror(f)) { log_error_errno(errno, "Failed to read from file %s: %m", fn); if (r == 0) From 875e7b25d84a111755dab79241c9e64e44836910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 7 Apr 2021 17:54:49 +0200 Subject: [PATCH 2/4] tmpfiles: rework condition check (!a && b) || (a && c) is replaced by (a ? c : b). path_startswith() != NULL is need to avoid type warning. --- src/tmpfiles/tmpfiles.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index df2b90e88f..8b58ac95e4 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -3251,7 +3251,11 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe for (size_t nj = 0; nj < ja->n_items; nj++) { Item *j = ja->items + nj; - if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) + if (!IN_SET(j->type, CREATE_DIRECTORY, + TRUNCATE_DIRECTORY, + CREATE_SUBVOLUME, + CREATE_SUBVOLUME_INHERIT_QUOTA, + CREATE_SUBVOLUME_NEW_QUOTA)) continue; if (path_equal(j->path, i->path)) { @@ -3259,8 +3263,9 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe break; } - if ((!candidate_item && path_startswith(i->path, j->path)) || - (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0))) + if (candidate_item + ? (path_startswith(j->path, candidate_item->path) && fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0) + : path_startswith(i->path, j->path) != NULL) candidate_item = j; } From 3dd61ee5be0291380d341571e138713d2f89125a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 7 Apr 2021 18:26:15 +0200 Subject: [PATCH 3/4] man: fix quickhelp listing in tmpfiles.d(5) Unlike many other small/big letter combos, this one has the recursive version attached to the lowercase letter. --- man/tmpfiles.d.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 55b763e26d..35b762ca3f 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -58,8 +58,8 @@ c+ /dev/char-device-to-[re]create mode user group - major b /dev/block-device-to-create mode user group - major:minor b+ /dev/block-device-to-[re]create mode user group - major:minor C /target/to/create - - - - /source/to/copy -x /path-or-glob/to/ignore - - - - - -X /path-or-glob/to/ignore/recursively - - - - - +x /path-or-glob/to/ignore/recursively - - - - - +X /path-or-glob/to/ignore - - - - - r /empty/dir/to/remove - - - - - R /dir/to/remove/recursively - - - - - z /path-or-glob/to/adjust/mode mode user group - - From 1672be86021b5ae8e80d095409a4fffcba7cbb75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 7 Apr 2021 22:35:19 +0200 Subject: [PATCH 4/4] TEST-22-TMPFILES: add reproducer for bug with X --- test/units/testsuite-22.11.sh | 141 ++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 test/units/testsuite-22.11.sh diff --git a/test/units/testsuite-22.11.sh b/test/units/testsuite-22.11.sh new file mode 100755 index 0000000000..21ef210cd1 --- /dev/null +++ b/test/units/testsuite-22.11.sh @@ -0,0 +1,141 @@ +#! /bin/bash + +set -e +set -x + +rm -fr /tmp/x +mkdir /tmp/x + +# +# 'x' +# +mkdir -p /tmp/x/{1,2} +touch /tmp/x/1/{x1,x2} /tmp/x/2/{y1,y2} /tmp/x/{z1,z2} + +systemd-tmpfiles --clean - <