summaryrefslogtreecommitdiffstats
path: root/src/basic/unit-file.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-09-29 15:21:38 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-10-06 05:28:19 +0200
commit95ef0eaf0d5cd43fcc8e9eb541f2c342f25f8f2f (patch)
tree25d44dfc133208f4b9cea49b39866946b3d30365 /src/basic/unit-file.c
parentMerge pull request #20937 from poettering/sync-split (diff)
downloadsystemd-95ef0eaf0d5cd43fcc8e9eb541f2c342f25f8f2f.tar.xz
systemd-95ef0eaf0d5cd43fcc8e9eb541f2c342f25f8f2f.zip
unit-file: tighten unit file discovery checks
Only accept DT_REG/DT_LNK/DT_DIR entries, ignore all others. Only accpet DT_REG/DT_LNK for file names that are valid unit file names. Only accept DT_DIR for filenames that are valid unit file names which are suffixed by .d, .wants, .requires This doesn't really fix any bugs, but tightens what we insert into the lookup tables.
Diffstat (limited to 'src/basic/unit-file.c')
-rw-r--r--src/basic/unit-file.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c
index 00be0601dc..bbe439da05 100644
--- a/src/basic/unit-file.c
+++ b/src/basic/unit-file.c
@@ -275,8 +275,8 @@ int unit_file_build_name_map(
}
STRV_FOREACH(dir, (char**) lp->search_path) {
- struct dirent *de;
_cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
d = opendir(*dir);
if (!d) {
@@ -286,18 +286,53 @@ int unit_file_build_name_map(
}
FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {
- char *filename;
_unused_ _cleanup_free_ char *_filename_free = NULL;
_cleanup_free_ char *simplified = NULL;
- const char *suffix, *dst = NULL;
- bool valid_unit_name;
-
- valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY);
+ const char *dst = NULL;
+ char *filename;
/* We only care about valid units and dirs with certain suffixes, let's ignore the
* rest. */
- if (!valid_unit_name &&
- !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d"))
+
+ if (IN_SET(de->d_type, DT_REG, DT_LNK)) {
+
+ if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY))
+ continue;
+
+ /* Accept a regular file or symlink whose name is a valid unit file name. */
+
+ } else if (de->d_type == DT_DIR) {
+ bool valid_dir_name = false;
+ const char *suffix;
+
+ /* Also accept a directory whose name is a valid unit file name ending in
+ * .wants/, .requires/ or .d/ */
+
+ if (!paths) /* Skip directories early unless path_cache is requested */
+ continue;
+
+ FOREACH_STRING(suffix, ".wants", ".requires", ".d") {
+ _cleanup_free_ char *chopped = NULL;
+ const char *e;
+
+ e = endswith(de->d_name, suffix);
+ if (!e)
+ continue;
+
+ chopped = strndup(de->d_name, e - de->d_name);
+ if (!chopped)
+ return log_oom();
+
+ if (unit_name_is_valid(chopped, UNIT_NAME_ANY) ||
+ unit_type_from_string(chopped) >= 0) {
+ valid_dir_name = true;
+ break;
+ }
+ }
+
+ if (!valid_dir_name)
+ continue;
+ } else
continue;
filename = path_join(*dir, de->d_name);
@@ -313,9 +348,8 @@ int unit_file_build_name_map(
} else
_filename_free = filename; /* Make sure we free the filename. */
- if (!valid_unit_name)
+ if (!IN_SET(de->d_type, DT_REG, DT_LNK))
continue;
- assert_se(suffix = strrchr(de->d_name, '.'));
/* search_path is ordered by priority (highest first). If the name is already mapped
* to something (incl. itself), it means that we have already seen it, and we should