]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pretty-print: make conf_files_cat() not show files outside of the specified root.
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 29 Jun 2025 20:22:53 +0000 (05:22 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 11 Jul 2025 01:42:08 +0000 (10:42 +0900)
Then, make the function show the original and resolved path if they are
different.

With this change, procfs needs to be mounted on /proc/, hence the test
code is slightly updated.

src/shared/pretty-print.c
src/shared/pretty-print.h
test/units/TEST-65-ANALYZE.sh

index 65f77e4cc9edeeed5fe66817ad6d99039b9f57f2..cbcf2a4be21c92cfdcba0129af0cecc3b056107d 100644 (file)
@@ -6,6 +6,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "chase.h"
 #include "color-util.h"
 #include "conf-files.h"
 #include "constants.h"
@@ -13,6 +14,7 @@
 #include "errno-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "log.h"
 #include "path-util.h"
 #include "pretty-print.h"
@@ -184,12 +186,15 @@ int terminal_urlify_man(const char *page, const char *section, char **ret) {
         return terminal_urlify(url, text, ret);
 }
 
-static int cat_file(const char *filename, bool *newline, CatFlags flags) {
+static int cat_file(const ConfFile *c, bool *newline, CatFlags flags) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_free_ char *urlified = NULL, *section = NULL, *old_section = NULL;
         int r;
 
-        assert(filename);
+        assert(c);
+        assert(c->original_path);
+        assert(c->resolved_path);
+        assert(c->fd >= 0);
 
         if (newline) {
                 if (*newline)
@@ -197,25 +202,29 @@ static int cat_file(const char *filename, bool *newline, CatFlags flags) {
                 *newline = true;
         }
 
-        r = terminal_urlify_path(filename, NULL, &urlified);
+        bool resolved = !path_equal(c->original_path, c->resolved_path);
+
+        r = terminal_urlify_path(c->resolved_path, NULL, &urlified);
         if (r < 0)
-                return log_error_errno(r, "Failed to urlify path \"%s\": %m", filename);
+                return log_error_errno(r, "Failed to urlify path \"%s\": %m", c->resolved_path);
 
-        printf("%s# %s%s\n",
+        printf("%s# %s%s%s%s\n",
                ansi_highlight_blue(),
+               resolved ? c->original_path : "",
+               resolved ? " -> " : "",
                urlified,
                ansi_normal());
 
-        f = fopen(filename, "re");
+        f = fopen(FORMAT_PROC_FD_PATH(c->fd), "re");
         if (!f)
-                return log_error_errno(errno, "Failed to open \"%s\": %m", filename);
+                return log_error_errno(errno, "Failed to open \"%s\": %m", c->resolved_path);
 
         for (bool continued = false;;) {
                 _cleanup_free_ char *line = NULL;
 
                 r = read_line(f, LONG_LINE_MAX, &line);
                 if (r < 0)
-                        return log_error_errno(r, "Failed to read \"%s\": %m", filename);
+                        return log_error_errno(r, "Failed to read \"%s\": %m", c->resolved_path);
                 if (r == 0)
                         break;
 
@@ -296,15 +305,43 @@ static int cat_file(const char *filename, bool *newline, CatFlags flags) {
         return 0;
 }
 
-int cat_files(const char *file, char **dropins, CatFlags flags) {
+int cat_files_full(const ConfFile *file, ConfFile * const *dropins, size_t n_dropins, CatFlags flags) {
         bool newline = false;
         int ret = 0;
 
+        assert(dropins || n_dropins == 0);
+
         if (file)
                 ret = cat_file(file, &newline, flags);
 
+        FOREACH_ARRAY(i, dropins, n_dropins)
+                RET_GATHER(ret, cat_file(*i, &newline, flags));
+
+        return ret;
+}
+
+static int cat_file_by_path(const char *p, bool *newline, CatFlags flags) {
+        _cleanup_(conf_file_freep) ConfFile *c = NULL;
+        int r;
+
+        assert(p);
+
+        r = conf_file_new(p, /* root = */ NULL, CHASE_MUST_BE_REGULAR, &c);
+        if (r < 0)
+                return log_error_errno(r, "Failed to chase '%s': %m", p);
+
+        return cat_file(c, newline, flags);
+}
+
+int cat_files(const char *file, char **dropins, CatFlags flags) {
+        bool newline = false;
+        int ret = 0;
+
+        if (file)
+                ret = cat_file_by_path(file, &newline, flags);
+
         STRV_FOREACH(path, dropins)
-                RET_GATHER(ret, cat_file(*path, &newline, flags));
+                RET_GATHER(ret, cat_file_by_path(*path, &newline, flags));
 
         return ret;
 }
@@ -384,8 +421,7 @@ static int guess_type(const char **name, char ***ret_prefixes, bool *ret_is_coll
 }
 
 int conf_files_cat(const char *root, const char *name, CatFlags flags) {
-        _cleanup_strv_free_ char **dirs = NULL, **files = NULL;
-        _cleanup_free_ char *path = NULL;
+        _cleanup_strv_free_ char **dirs = NULL;
         char **prefixes = NULL; /* explicit initialization to appease gcc */
         bool is_collection;
         const char *extension;
@@ -416,17 +452,18 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) {
         }
 
         /* First locate the main config file, if any */
+        _cleanup_(conf_file_freep) ConfFile *c = NULL;
         if (!is_collection) {
                 STRV_FOREACH(prefix, prefixes) {
-                        path = path_join(root, *prefix, name);
-                        if (!path)
+                        _cleanup_free_ char *p = path_join(*prefix, name);
+                        if (!p)
                                 return log_oom();
-                        if (access(path, F_OK) == 0)
+
+                        if (conf_file_new(p, root, CHASE_MUST_BE_REGULAR, &c) >= 0)
                                 break;
-                        path = mfree(path);
                 }
 
-                if (!path)
+                if (!c)
                         printf("%s# Main configuration file %s not found%s\n",
                                ansi_highlight_magenta(),
                                name,
@@ -434,7 +471,10 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) {
         }
 
         /* Then locate the drop-ins, if any */
-        r = conf_files_list_strv(&files, extension, root, 0, (const char* const*) dirs);
+        ConfFile **dropins = NULL;
+        size_t n_dropins = 0;
+        CLEANUP_ARRAY(dropins, n_dropins, conf_file_free_many);
+        r = conf_files_list_strv_full(extension, root, CONF_FILES_REGULAR | CONF_FILES_FILTER_MASKED, (const char* const*) dirs, &dropins, &n_dropins);
         if (r < 0)
                 return log_error_errno(r, "Failed to query file list: %m");
 
@@ -442,7 +482,7 @@ int conf_files_cat(const char *root, const char *name, CatFlags flags) {
         if (is_collection)
                 flags |= CAT_FORMAT_HAS_SECTIONS;
 
-        return cat_files(path, files, flags);
+        return cat_files_full(c, dropins, n_dropins, flags);
 }
 
 int terminal_tint_color(double hue, char **ret) {
index fc0ba5355f801558ffd36e45676b7b6273243668..56491886fa21f656b0c3b63c482b8fe0890fa644 100644 (file)
@@ -30,6 +30,7 @@ typedef enum CatFlags {
         CAT_TLDR                = 1 << 2,  /* Only print comments and relevant section headers */
 } CatFlags;
 
+int cat_files_full(const ConfFile *file, ConfFile * const *dropins, size_t n_dropins, CatFlags flags);
 int cat_files(const char *file, char **dropins, CatFlags flags);
 int conf_files_cat(const char *root, const char *name, CatFlags flags);
 
index 7fd4543e76aba2f552ccaf59a1b670db33554bb4..5a5a9ba206dc67e4bd90b36cafe19e6f7da28f42 100755 (executable)
@@ -313,6 +313,7 @@ if [[ ! -v ASAN_OPTIONS ]]; then
     # check that systemd-analyze cat-config paths work in a chroot
     mkdir -p /tmp/root
     mount --bind / /tmp/root
+    mount -t proc proc /tmp/root/proc
     if mountpoint -q /usr; then
         mount --bind /usr /tmp/root/usr
     fi