From b50846055ee7e846697ea9f7fcf959bf0bfb8066 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 12 Sep 2017 16:57:33 +0200 Subject: [PATCH] exec-util,conf-files: skip non-executable files in execute_directories() Fixes: #6787 --- src/basic/conf-files.c | 44 +++++++++++++++++----- src/basic/conf-files.h | 10 +++-- src/basic/exec-util.c | 2 +- src/binfmt/binfmt.c | 2 +- .../environment-d-generator.c | 2 +- src/hwdb/hwdb.c | 2 +- src/journal/catalog.c | 2 +- src/modules-load/modules-load.c | 2 +- src/network/netdev/netdev.c | 2 +- src/network/networkd-network.c | 2 +- src/resolve/resolved-dns-trust-anchor.c | 2 +- src/shared/conf-parser.c | 4 +- src/shared/dropin.c | 2 +- src/shared/install.c | 4 +- src/sleep/sleep.c | 5 ++- src/sysctl/sysctl.c | 2 +- src/sysusers/sysusers.c | 2 +- src/test/test-conf-files.c | 4 +- src/tmpfiles/tmpfiles.c | 2 +- src/udev/net/link-config.c | 2 +- src/udev/udev-rules.c | 2 +- src/udev/udevadm-hwdb.c | 2 +- 22 files changed, 68 insertions(+), 35 deletions(-) diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index b8f0f5d..21921a4 100644 --- a/src/basic/conf-files.c +++ b/src/basic/conf-files.c @@ -32,11 +32,12 @@ #include "macro.h" #include "missing.h" #include "path-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "util.h" -static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) { +static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) { _cleanup_closedir_ DIR *dir = NULL; const char *dirpath; struct dirent *de; @@ -59,6 +60,31 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char if (!dirent_is_file_with_suffix(de, suffix)) continue; + if (flags & CONF_FILES_EXECUTABLE) { + struct stat st; + + /* As requested: check if the file is marked exectuable. Note that we don't check access(X_OK) + * here, as we care about whether the file is marked executable at all, and not whether it is + * executable for us, because if such errors are stuff we should log about. */ + + if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) { + log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", dirpath, de->d_name); + continue; + } + + /* We only want executable regular files (or symlinks to them), or symlinks to /dev/null */ + if (S_ISREG(st.st_mode)) { + if ((st.st_mode & 0111) == 0) { /* not executable */ + log_debug("Ignoring %s/%s, as it is not marked executable.", dirpath, de->d_name); + continue; + } + + } else if (!null_or_empty(&st)) { /* /dev/null? */ + log_debug("Ignoring %s/%s, as it is not a regular file (or symlink to /dev/null).", dirpath, de->d_name); + continue; + } + } + p = strjoin(dirpath, "/", de->d_name); if (!p) return -ENOMEM; @@ -87,7 +113,7 @@ static int base_cmp(const void *a, const void *b) { return strcmp(basename(s1), basename(s2)); } -static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) { +static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) { _cleanup_hashmap_free_ Hashmap *fh = NULL; char **files, **p; int r; @@ -103,7 +129,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const return -ENOMEM; STRV_FOREACH(p, dirs) { - r = files_add(fh, root, *p, suffix); + r = files_add(fh, suffix, root, flags, *p); if (r == -ENOMEM) return r; if (r < 0) @@ -120,7 +146,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const return 0; } -int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) { +int conf_files_list_strv(char ***strv, const char *suffix, const char *root, unsigned flags, const char* const* dirs) { _cleanup_strv_free_ char **copy = NULL; assert(strv); @@ -129,10 +155,10 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con if (!copy) return -ENOMEM; - return conf_files_list_strv_internal(strv, suffix, root, copy); + return conf_files_list_strv_internal(strv, suffix, root, flags, copy); } -int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) { +int conf_files_list(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dir, ...) { _cleanup_strv_free_ char **dirs = NULL; va_list ap; @@ -145,10 +171,10 @@ int conf_files_list(char ***strv, const char *suffix, const char *root, const ch if (!dirs) return -ENOMEM; - return conf_files_list_strv_internal(strv, suffix, root, dirs); + return conf_files_list_strv_internal(strv, suffix, root, flags, dirs); } -int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) { +int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, unsigned flags, const char *d) { _cleanup_strv_free_ char **dirs = NULL; assert(strv); @@ -157,5 +183,5 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, c if (!dirs) return -ENOMEM; - return conf_files_list_strv_internal(strv, suffix, root, dirs); + return conf_files_list_strv_internal(strv, suffix, root, flags, dirs); } diff --git a/src/basic/conf-files.h b/src/basic/conf-files.h index e00e0e8..20ecf6e 100644 --- a/src/basic/conf-files.h +++ b/src/basic/conf-files.h @@ -20,6 +20,10 @@ along with systemd; If not, see . ***/ -int conf_files_list(char ***ret, const char *suffix, const char *root, const char *dir, ...); -int conf_files_list_strv(char ***ret, const char *suffix, const char *root, const char* const* dirs); -int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs); +enum { + CONF_FILES_EXECUTABLE = 1, +}; + +int conf_files_list(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dir, ...); +int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsigned flags, const char* const* dirs); +int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs); diff --git a/src/basic/exec-util.c b/src/basic/exec-util.c index aced9e8..ade8511 100644 --- a/src/basic/exec-util.c +++ b/src/basic/exec-util.c @@ -111,7 +111,7 @@ static int do_execute( assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - r = conf_files_list_strv(&paths, NULL, NULL, (const char* const*) directories); + r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE, (const char* const*) directories); if (r < 0) return r; diff --git a/src/binfmt/binfmt.c b/src/binfmt/binfmt.c index eeef04f..17af233 100644 --- a/src/binfmt/binfmt.c +++ b/src/binfmt/binfmt.c @@ -182,7 +182,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate binfmt.d files: %m"); goto finish; diff --git a/src/environment-d-generator/environment-d-generator.c b/src/environment-d-generator/environment-d-generator.c index 9c72502..55de685 100644 --- a/src/environment-d-generator/environment-d-generator.c +++ b/src/environment-d-generator/environment-d-generator.c @@ -58,7 +58,7 @@ static int load_and_print(void) { if (r < 0) return r; - r = conf_files_list_strv(&files, ".conf", NULL, (const char **) dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char **) dirs); if (r < 0) return r; diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c index ead4e17..c964a28 100644 --- a/src/hwdb/hwdb.c +++ b/src/hwdb/hwdb.c @@ -653,7 +653,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) { trie->nodes_count++; - r = conf_files_list_strv(&files, ".hwdb", arg_root, conf_file_dirs); + r = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate hwdb files: %m"); diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 886f6ef..f42be0a 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -479,7 +479,7 @@ int catalog_update(const char* database, const char* root, const char* const* di goto finish; } - r = conf_files_list_strv(&files, ".catalog", root, dirs); + r = conf_files_list_strv(&files, ".catalog", root, 0, dirs); if (r < 0) { log_error_errno(r, "Failed to get catalog files: %m"); goto finish; diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c index 615998a..6efebcd 100644 --- a/src/modules-load/modules-load.c +++ b/src/modules-load/modules-load.c @@ -264,7 +264,7 @@ int main(int argc, char *argv[]) { r = k; } - k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + k = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); if (k < 0) { log_error_errno(k, "Failed to enumerate modules-load.d files: %m"); if (r == 0) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index 1cf72bf..0e1a7d1 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -766,7 +766,7 @@ int netdev_load(Manager *manager) { while ((netdev = hashmap_first(manager->netdevs))) netdev_unref(netdev); - r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs); + r = conf_files_list_strv(&files, ".netdev", NULL, 0, network_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate netdev files: %m"); diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index a873e55..3b52a8a 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -322,7 +322,7 @@ int network_load(Manager *manager) { while ((network = manager->networks)) network_free(network); - r = conf_files_list_strv(&files, ".network", NULL, network_dirs); + r = conf_files_list_strv(&files, ".network", NULL, 0, network_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate network files: %m"); diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index dda9875..e169c8f 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -435,7 +435,7 @@ static int dns_trust_anchor_load_files( assert(suffix); assert(loader); - r = conf_files_list_nulstr(&files, suffix, NULL, trust_anchor_dirs); + r = conf_files_list_nulstr(&files, suffix, NULL, 0, trust_anchor_dirs); if (r < 0) return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix); diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index e08402e..8b01b3b 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -436,7 +436,7 @@ int config_parse_many_nulstr( _cleanup_strv_free_ char **files = NULL; int r; - r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); if (r < 0) return r; @@ -465,7 +465,7 @@ int config_parse_many( if (r < 0) return r; - r = conf_files_list_strv(&files, ".conf", NULL, (const char* const*) dropin_dirs); + r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dropin_dirs); if (r < 0) return r; diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 7d8fbeb..059b50d 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -203,7 +203,7 @@ int unit_file_find_dropin_paths( return 0; } - r = conf_files_list_strv(ret, file_suffix, NULL, (const char**) dirs); + r = conf_files_list_strv(ret, file_suffix, NULL, 0, (const char**) dirs); if (r < 0) return log_warning_errno(r, "Failed to create the list of configuration files: %m"); diff --git a/src/shared/install.c b/src/shared/install.c index d0a291b..9e4e0ea 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -2662,7 +2662,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres assert(presets); if (scope == UNIT_FILE_SYSTEM) - r = conf_files_list(&files, ".preset", root_dir, + r = conf_files_list(&files, ".preset", root_dir, 0, "/etc/systemd/system-preset", "/usr/local/lib/systemd/system-preset", "/usr/lib/systemd/system-preset", @@ -2671,7 +2671,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres #endif NULL); else if (scope == UNIT_FILE_GLOBAL) - r = conf_files_list(&files, ".preset", root_dir, + r = conf_files_list(&files, ".preset", root_dir, 0, "/etc/systemd/user-preset", "/usr/local/lib/systemd/user-preset", "/usr/lib/systemd/user-preset", diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 3bac78b..4c171a2 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -91,7 +91,10 @@ static int execute(char **modes, char **states) { arg_verb, NULL }; - static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL}; + static const char* const dirs[] = { + SYSTEM_SLEEP_PATH, + NULL + }; int r; _cleanup_fclose_ FILE *f = NULL; diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c index 41a6dcb..ce4ff8c 100644 --- a/src/sysctl/sysctl.c +++ b/src/sysctl/sysctl.c @@ -280,7 +280,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate sysctl.d files: %m"); goto finish; diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index 448f584..e384219 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1798,7 +1798,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate sysusers.d files: %m"); goto finish; diff --git a/src/test/test-conf-files.c b/src/test/test-conf-files.c index 22b7c61..777b5ca 100644 --- a/src/test/test-conf-files.c +++ b/src/test/test-conf-files.c @@ -75,7 +75,7 @@ static void test_conf_files_list(bool use_root) { log_debug("/* Check when filtered by suffix */"); - assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0); + assert_se(conf_files_list(&found_files, ".conf", root_dir, 0, search_1, search_2, NULL) == 0); strv_print(found_files); assert_se(found_files); @@ -84,7 +84,7 @@ static void test_conf_files_list(bool use_root) { assert_se(found_files[2] == NULL); log_debug("/* Check when unfiltered */"); - assert_se(conf_files_list(&found_files2, NULL, root_dir, search_1, search_2, NULL) == 0); + assert_se(conf_files_list(&found_files2, NULL, root_dir, 0, search_1, search_2, NULL) == 0); strv_print(found_files2); assert_se(found_files2); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 875a886..3d3967f 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2300,7 +2300,7 @@ int main(int argc, char *argv[]) { _cleanup_strv_free_ char **files = NULL; char **f; - r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs); + r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, conf_file_dirs); if (r < 0) { log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m"); goto finish; diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 05a1863..6ece125 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -213,7 +213,7 @@ int link_config_load(link_config_ctx *ctx) { /* update timestamp */ paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true); - r = conf_files_list_strv(&files, ".link", NULL, link_dirs); + r = conf_files_list_strv(&files, ".link", NULL, 0, link_dirs); if (r < 0) return log_error_errno(r, "failed to enumerate link files: %m"); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 294a322..76a1d35 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -1533,7 +1533,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) { udev_rules_check_timestamp(rules); - r = conf_files_list_strv(&files, ".rules", NULL, rules_dirs); + r = conf_files_list_strv(&files, ".rules", NULL, 0, rules_dirs); if (r < 0) { log_error_errno(r, "failed to enumerate rules files: %m"); return udev_rules_unref(rules); diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 7688f81..4a23270 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -627,7 +627,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { } trie->nodes_count++; - err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs); + err = conf_files_list_strv(&files, ".hwdb", root, 0, conf_file_dirs); if (err < 0) { log_error_errno(err, "failed to enumerate hwdb files: %m"); rc = EXIT_FAILURE; -- 2.7.4