From d8a91c6b9f64017abfefbbf7da0daed590de372a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 21 Feb 2024 22:29:56 +0100 Subject: [PATCH] shared/conf-parser: use chase() in config_parse_many_files() 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 | 37 +++++++++++++++++-------------------- src/shared/conf-parser.h | 2 +- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index fba0001242..b1bc6c8a95 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -8,6 +8,7 @@ #include #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; + _cleanup_free_ char *fname = NULL; - f = fopen(*fn, "re"); - if (!f) { - if (errno == ENOENT) - continue; + r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", &fname, &f); + if (r == -ENOENT) + continue; + if (r < 0) + return r; - return -errno; - } - - 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; diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 2c75ba5d8b..9d08cbd677 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -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,