conf-files: add support for root_fd based operation
Let's make sure we can safely load configuration files based on a root fd, including XAT_FDROOT. (While we are at it, always pass path to root fs before fd to root fs, following our recently updated CODING_STYLE)
This commit is contained in:
+75
-19
@@ -481,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,
|
||||
int root_fd,
|
||||
const char* const* conf_files,
|
||||
char **files,
|
||||
const char *sections,
|
||||
@@ -502,17 +503,17 @@ static int config_parse_many_files(
|
||||
return log_oom_full(level);
|
||||
}
|
||||
|
||||
/* Pin and stat() all dropins */
|
||||
STRV_FOREACH(fn, files) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *fname = NULL;
|
||||
|
||||
r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", &fname, &f);
|
||||
r = chase_and_fopenat_unlocked(root_fd, *fn, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return log_full_errno(level, r, "Failed to open %s: %m", *fn);
|
||||
|
||||
int fd = fileno(f);
|
||||
assert(fd >= 0);
|
||||
|
||||
r = ordered_hashmap_ensure_put(&dropins, &config_file_hash_ops_fclose, *fn, f);
|
||||
if (r < 0) {
|
||||
@@ -537,11 +538,10 @@ static int config_parse_many_files(
|
||||
return log_oom_full(level);
|
||||
}
|
||||
|
||||
/* First read the first found main config file. */
|
||||
/* First process the first found main config file. */
|
||||
STRV_FOREACH(fn, conf_files) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
r = chase_and_fopen_unlocked(*fn, root, CHASE_AT_RESOLVE_IN_ROOT, "re", NULL, &f);
|
||||
r = chase_and_fopenat_unlocked(root_fd, *fn, CHASE_AT_RESOLVE_IN_ROOT|CHASE_MUST_BE_REGULAR, "re", /* ret_path= */ NULL, &f);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
@@ -572,7 +572,6 @@ static int config_parse_many_files(
|
||||
}
|
||||
|
||||
/* Then read all the drop-ins. */
|
||||
|
||||
const char *path_dropin;
|
||||
FILE *f_dropin;
|
||||
ORDERED_HASHMAP_FOREACH_KEY(f_dropin, path_dropin, dropins) {
|
||||
@@ -594,12 +593,39 @@ static int config_parse_many_files(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int normalize_root_fd(const char *root, int *root_fd, int *ret_opened_fd) {
|
||||
assert(root_fd);
|
||||
assert(ret_opened_fd);
|
||||
|
||||
/* Normalizes a root dir specification: if root_fd is already valid, keep it. Otherwise, we open the
|
||||
* specified dir */
|
||||
|
||||
if (*root_fd >= 0 || IN_SET(*root_fd, AT_FDCWD, XAT_FDROOT)) {
|
||||
*ret_opened_fd = -EBADF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (empty_or_root(root)) {
|
||||
*root_fd = XAT_FDROOT;
|
||||
*ret_opened_fd = -EBADF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd = open(root, O_CLOEXEC|O_PATH|O_DIRECTORY);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open root directory '%s': %m", root);
|
||||
|
||||
*ret_opened_fd = *root_fd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse each config file in the directories specified as strv. */
|
||||
int config_parse_many(
|
||||
int config_parse_many_full(
|
||||
const char* const* conf_files,
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *sections,
|
||||
ConfigItemLookup lookup,
|
||||
const void *table,
|
||||
@@ -615,14 +641,33 @@ int config_parse_many(
|
||||
assert(dropin_dirname);
|
||||
assert(table);
|
||||
|
||||
r = conf_files_list_dropins(&files, dropin_dirname, root,
|
||||
FLAGS_SET(flags, CONFIG_PARSE_WARN) ? CONF_FILES_WARN : 0,
|
||||
conf_file_dirs);
|
||||
_cleanup_close_ int opened_root_fd = -EBADF;
|
||||
r = normalize_root_fd(root, &root_fd, &opened_root_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conf_files_list_dropins(
|
||||
&files,
|
||||
dropin_dirname,
|
||||
root,
|
||||
root_fd,
|
||||
FLAGS_SET(flags, CONFIG_PARSE_WARN) ? CONF_FILES_WARN : 0,
|
||||
conf_file_dirs);
|
||||
if (r < 0)
|
||||
return log_full_errno(FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_WARNING : LOG_DEBUG, r,
|
||||
"Failed to list drop-ins in %s: %m", dropin_dirname);
|
||||
|
||||
r = config_parse_many_files(root, conf_files, files, sections, lookup, table, flags, userdata, ret_stats_by_path);
|
||||
r = config_parse_many_files(
|
||||
root,
|
||||
root_fd,
|
||||
conf_files,
|
||||
files,
|
||||
sections,
|
||||
lookup,
|
||||
table,
|
||||
flags,
|
||||
userdata,
|
||||
ret_stats_by_path);
|
||||
if (r < 0)
|
||||
return r; /* config_parse_many_files() logs internally. */
|
||||
|
||||
@@ -634,6 +679,7 @@ int config_parse_many(
|
||||
|
||||
int config_parse_standard_file_with_dropins_full(
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *main_file, /* A path like "systemd/frobnicator.conf" */
|
||||
const char *sections,
|
||||
ConfigItemLookup lookup,
|
||||
@@ -643,12 +689,15 @@ int config_parse_standard_file_with_dropins_full(
|
||||
Hashmap **ret_stats_by_path,
|
||||
char ***ret_dropin_files) {
|
||||
|
||||
const char* const *conf_paths = (const char* const*) CONF_PATHS_STRV("");
|
||||
_cleanup_strv_free_ char **configs = NULL;
|
||||
const char* const *conf_file_dirs = (const char* const*) CONF_PATHS_STRV("");
|
||||
_cleanup_strv_free_ char **conf_files = NULL;
|
||||
int r, level = FLAGS_SET(flags, CONFIG_PARSE_WARN) ? LOG_WARNING : LOG_DEBUG;
|
||||
|
||||
/* Build the list of main config files */
|
||||
r = strv_extend_strv_biconcat(&configs, root, conf_paths, main_file);
|
||||
r = strv_extend_strv_concat(
|
||||
&conf_files,
|
||||
conf_file_dirs,
|
||||
main_file);
|
||||
if (r < 0)
|
||||
return log_oom_full(level);
|
||||
|
||||
@@ -656,11 +705,12 @@ int config_parse_standard_file_with_dropins_full(
|
||||
if (!dropin_dirname)
|
||||
return log_oom_full(level);
|
||||
|
||||
return config_parse_many(
|
||||
(const char* const*) configs,
|
||||
conf_paths,
|
||||
return config_parse_many_full(
|
||||
(const char* const*) conf_files,
|
||||
conf_file_dirs,
|
||||
dropin_dirname,
|
||||
root,
|
||||
root_fd,
|
||||
sections,
|
||||
lookup,
|
||||
table,
|
||||
@@ -692,7 +742,13 @@ static int dropins_get_stats_by_path(
|
||||
if (!strextend(&dropin_dirname, ".d"))
|
||||
return -ENOMEM;
|
||||
|
||||
r = conf_files_list_dropins(&files, dropin_dirname, /* root= */ NULL, /* flags= */ 0, conf_file_dirs);
|
||||
r = conf_files_list_dropins(
|
||||
&files,
|
||||
dropin_dirname,
|
||||
/* root= */ NULL,
|
||||
/* root_fd= */ XAT_FDROOT,
|
||||
/* flags= */ 0,
|
||||
conf_file_dirs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "conf-parser-forward.h"
|
||||
#include "shared-forward.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
|
||||
/* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
|
||||
@@ -66,11 +66,12 @@ int config_parse(
|
||||
void *userdata,
|
||||
struct stat *ret_stat); /* possibly NULL */
|
||||
|
||||
int config_parse_many(
|
||||
int config_parse_many_full(
|
||||
const char* const* conf_files, /* possibly empty */
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *sections, /* nulstr */
|
||||
ConfigItemLookup lookup,
|
||||
const void *table,
|
||||
@@ -79,8 +80,34 @@ int config_parse_many(
|
||||
Hashmap **ret_stats_by_path, /* possibly NULL */
|
||||
char ***ret_dropin_files); /* possibly NULL */
|
||||
|
||||
static inline int config_parse_many(
|
||||
const char* const* conf_files, /* possibly empty */
|
||||
const char* const* conf_file_dirs,
|
||||
const char *dropin_dirname,
|
||||
const char *sections, /* nulstr */
|
||||
ConfigItemLookup lookup,
|
||||
const void *table,
|
||||
ConfigParseFlags flags,
|
||||
void *userdata) {
|
||||
|
||||
return config_parse_many_full(
|
||||
conf_files,
|
||||
conf_file_dirs,
|
||||
dropin_dirname,
|
||||
/* root= */ NULL,
|
||||
/* root_fd= */ XAT_FDROOT,
|
||||
sections,
|
||||
lookup,
|
||||
table,
|
||||
flags,
|
||||
userdata,
|
||||
/* ret_stats_by_path= */ NULL,
|
||||
/* ret_drop_in_files= */ NULL);
|
||||
}
|
||||
|
||||
int config_parse_standard_file_with_dropins_full(
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *main_file, /* A path like "systemd/frobnicator.conf" */
|
||||
const char *sections,
|
||||
ConfigItemLookup lookup,
|
||||
@@ -99,6 +126,7 @@ static inline int config_parse_standard_file_with_dropins(
|
||||
void *userdata) {
|
||||
return config_parse_standard_file_with_dropins_full(
|
||||
/* root= */ NULL,
|
||||
/* root_fd= */ XAT_FDROOT,
|
||||
main_file,
|
||||
sections,
|
||||
lookup,
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "fd-util.h"
|
||||
#include "kernel-config.h"
|
||||
#include "path-util.h"
|
||||
|
||||
int load_kernel_install_conf(
|
||||
int load_kernel_install_conf_at(
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *conf_root,
|
||||
char **ret_machine_id,
|
||||
char **ret_boot_root,
|
||||
@@ -26,16 +28,19 @@ int load_kernel_install_conf(
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(root_fd >= 0 || IN_SET(root_fd, AT_FDCWD, XAT_FDROOT));
|
||||
|
||||
if (conf_root) {
|
||||
_cleanup_free_ char *conf = path_join(conf_root, "install.conf");
|
||||
if (!conf)
|
||||
return log_oom();
|
||||
|
||||
r = config_parse_many(
|
||||
r = config_parse_many_full(
|
||||
STRV_MAKE_CONST(conf),
|
||||
STRV_MAKE_CONST(conf_root),
|
||||
"install.conf.d",
|
||||
/* root= */ NULL, /* $KERNEL_INSTALL_CONF_ROOT and --root are independent */
|
||||
root,
|
||||
root_fd,
|
||||
/* sections= */ NULL,
|
||||
config_item_table_lookup, items,
|
||||
CONFIG_PARSE_WARN,
|
||||
@@ -45,6 +50,7 @@ int load_kernel_install_conf(
|
||||
} else
|
||||
r = config_parse_standard_file_with_dropins_full(
|
||||
root,
|
||||
root_fd,
|
||||
"kernel/install.conf",
|
||||
/* sections= */ NULL,
|
||||
config_item_table_lookup, items,
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "shared-forward.h"
|
||||
|
||||
int load_kernel_install_conf(
|
||||
int load_kernel_install_conf_at(
|
||||
const char *root,
|
||||
int root_fd,
|
||||
const char *conf_root,
|
||||
char **ret_machine_id,
|
||||
char **ret_boot_root,
|
||||
char **ret_layout,
|
||||
char **ret_initrd_generator,
|
||||
char **ret_uki_generator);
|
||||
|
||||
static inline int load_kernel_install_conf(
|
||||
const char *root,
|
||||
const char *conf_root,
|
||||
char **ret_machine_id,
|
||||
char **ret_boot_root,
|
||||
char **ret_layout,
|
||||
char **ret_initrd_generator,
|
||||
char **ret_uki_generator) {
|
||||
|
||||
return load_kernel_install_conf_at(root, XAT_FDROOT, conf_root, ret_machine_id, ret_boot_root, ret_layout, ret_initrd_generator, ret_uki_generator);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user