chiark / gitweb /
exec-util,conf-files: skip non-executable files in execute_directories()
authorLennart Poettering <lennart@poettering.net>
Tue, 12 Sep 2017 14:57:33 +0000 (16:57 +0200)
committerSven Eden <yamakuzure@gmx.net>
Mon, 25 Sep 2017 12:37:36 +0000 (14:37 +0200)
Fixes: #6787
src/basic/conf-files.c
src/basic/conf-files.h
src/basic/exec-util.c
src/shared/conf-parser.c
src/sleep/sleep.c
src/test/test-conf-files.c

index b8f0f5d03d227e370d0db4b6a5aa07e152b89016..21921a43e104c889a0fb848c91db4891ced44ba0 100644 (file)
 #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);
 }
index e00e0e81fbd3713e5a5d8d49f1285e2227c6a6a5..20ecf6e5f15da0ec9dd8d70ce0adccb67b44d9e0 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-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);
index e542d5c93ec22c43c2819cf8ffa26695dea97566..861af3264b015d3c3c0f9d8cecd2ce3dd6fb2f47 100644 (file)
@@ -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;
 
index c8a95c7f30117fe8620fa7cf789766b92b9e7c2b..2437c1ca7efee0302327082d91b360602dc56b64 100644 (file)
@@ -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;
 
index 4b402abcd1cdcf880b152306798620ff1c48a326..01fa223490e2fd84b7150909c9819419e2594a06 100644 (file)
@@ -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;
index 22b7c61204acab2a228a4e36ed3d743311e33e19..777b5ca32b0ec8d4ae61c4581e876e0c440e19f5 100644 (file)
@@ -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);