From 3053a76e3f84eea8e4f0f8245efadda5c4917c1b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 12 Sep 2017 16:57:33 +0200 Subject: 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/shared/conf-parser.c | 10 ++-------- src/sleep/sleep.c | 5 ++++- src/test/test-conf-files.c | 4 ++-- 6 files changed, 51 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c index b8f0f5d03..21921a43e 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 e00e0e81f..20ecf6e5f 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 e542d5c93..861af3264 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/shared/conf-parser.c b/src/shared/conf-parser.c index c8a95c7f3..2437c1ca7 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -435,7 +435,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; @@ -734,11 +734,6 @@ int config_parse_path( assert(rvalue); assert(data); - if (isempty(rvalue)) { - n = NULL; - goto finalize; - } - if (!utf8_is_valid(rvalue)) { log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); return fatal ? -ENOEXEC : 0; @@ -757,7 +752,6 @@ int config_parse_path( path_kill_slashes(n); -finalize: free(*s); *s = n; diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c index 4b402abcd..01fa22349 100644 --- a/src/sleep/sleep.c +++ b/src/sleep/sleep.c @@ -94,7 +94,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/test/test-conf-files.c b/src/test/test-conf-files.c index 22b7c6120..777b5ca32 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); -- cgit v1.2.3