shared/conf-parser: use chase() in config_parse_many_files()
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 21 Feb 2024 21:29:56 +0000 (22:29 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 7 Mar 2024 17:49:44 +0000 (18:49 +0100)
The function was partially implementing chroot lookups. It would be given
file names that were prefixed with the chroot, so it would mostly work.
But if any of those files were symlinks, fopen() would do the wrong thing.

Also we don't need locking.

So give 'root' as the argument and use chase_and_fopen_unlocked() to get
proper chroot-aware lookups.

The only place where config_parse_many() is called with root is is repart.c.
So this is a follow-up for e594a3b154bd06c535a934a1cc7231b1ef76df73 and
34f2fd5096cdb26ef57998740b1b876332d968fc.

src/shared/conf-parser.c
src/shared/conf-parser.h

index fba0001242a10c727547ee8f8716bdc83fdaab55..b1bc6c8a9503ff4ba99fe2577281bb3c476f22a6 100644 (file)
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 
 #include "alloc-util.h"
+#include "chase.h"
 #include "conf-files.h"
 #include "conf-parser.h"
 #include "constants.h"
@@ -480,6 +481,7 @@ int hashmap_put_stats_by_path(Hashmap **stats_by_path, const char *path, const s
 }
 
 static int config_parse_many_files(
+                const char *root,
                 const char* const* conf_files,
                 char **files,
                 const char *sections,
@@ -502,19 +504,16 @@ static int config_parse_many_files(
         }
 
         STRV_FOREACH(fn, files) {
-                _cleanup_free_ struct stat *st_dropin = NULL;
                 _cleanup_fclose_ FILE *f = NULL;
-                int fd;
-
-                f = fopen(*fn, "re");
-                if (!f) {
-                        if (errno == ENOENT)
-                                continue;
+                _cleanup_free_ char *fname = NULL;
 
-                        return -errno;
-                }
+                r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", &fname, &f);
+                if (r == -ENOENT)
+                        continue;
+                if (r < 0)
+                        return r;
 
-                fd = fileno(f);
+                int fd = fileno(f);
 
                 r = ordered_hashmap_ensure_put(&dropins, &config_file_hash_ops_fclose, *fn, f);
                 if (r < 0) {
@@ -527,7 +526,7 @@ static int config_parse_many_files(
                 /* Get inodes for all drop-ins. Later we'll verify if main config is a symlink to or is
                  * symlinked as one of them. If so, we skip reading main config file directly. */
 
-                st_dropin = new(struct stat, 1);
+                _cleanup_free_ struct stat *st_dropin = new(struct stat, 1);
                 if (!st_dropin)
                         return -ENOMEM;
 
@@ -543,13 +542,11 @@ static int config_parse_many_files(
         STRV_FOREACH(fn, conf_files) {
                 _cleanup_fclose_ FILE *f = NULL;
 
-                f = fopen(*fn, "re");
-                if (!f) {
-                        if (errno == ENOENT)
-                                continue;
-
-                        return -errno;
-                }
+                r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", NULL, &f);
+                if (r == -ENOENT)
+                        continue;
+                if (r < 0)
+                        return r;
 
                 if (inodes) {
                         if (fstat(fileno(f), &st) < 0)
@@ -642,7 +639,7 @@ int config_parse_config_file(
 
         const char *sysconf_file = strjoina(SYSCONF_DIR, "/", conf_file);
 
-        return config_parse_many_files(STRV_MAKE_CONST(sysconf_file), dropins,
+        return config_parse_many_files(NULL, STRV_MAKE_CONST(sysconf_file), dropins,
                                        sections, lookup, table, flags, userdata, NULL);
 }
 
@@ -672,7 +669,7 @@ int config_parse_many(
         if (r < 0)
                 return r;
 
-        r = config_parse_many_files(conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
+        r = config_parse_many_files(root, conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
         if (r < 0)
                 return r;
 
index 2c75ba5d8b8f19161108d022019ebcb686be95d4..9d08cbd6770b00e488413819a241a349c94ace99 100644 (file)
@@ -106,7 +106,7 @@ int config_parse_many(
                 const char* const* conf_file_dirs,
                 const char *dropin_dirname,
                 const char *root,
-                const char *sections,       /* nulstr */
+                const char *sections,         /* nulstr */
                 ConfigItemLookup lookup,
                 const void *table,
                 ConfigParseFlags flags,