1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-03 05:18:09 +03:00

kernel-install: do not resolve symlink in paths passed to plugins

When we resolve symlinks, paths (especially filenames) may be changed,
but plugins may expect to see the kernel added under the name specified,
not under the final name that the symlink chain resolves to.

This makes symlinks in specified paths that passed to plugins are not
resolved when neither --root nor --image specified.

Fixes #29317.
This commit is contained in:
Yu Watanabe 2023-11-21 10:18:57 +09:00 committed by Luca Boccassi
parent b0c11b5a0f
commit 54bc114fec

View File

@ -197,9 +197,20 @@ static int context_copy(const Context *source, Context *ret) {
}
static int context_open_root(Context *c) {
int r;
assert(c);
assert(c->rfd < 0);
if (isempty(arg_root))
return 0;
r = path_is_root(arg_root);
if (r < 0)
return log_error_errno(r, "Failed to determine if '%s' is the root directory: %m", arg_root);
if (r > 0)
return 0;
c->rfd = open(empty_to_root(arg_root), O_CLOEXEC | O_DIRECTORY | O_PATH);
if (c->rfd < 0)
return log_error_errno(errno, "Failed to open root directory '%s': %m", empty_to_root(arg_root));
@ -301,7 +312,7 @@ static int context_set_version(Context *c, const char *s) {
return context_set_string(s, "command line", "kernel version", &c->version);
}
static int context_set_path(Context *c, int rfd, const char *s, const char *source, const char *name, char **dest) {
static int context_set_path(Context *c, const char *s, const char *source, const char *name, char **dest) {
char *p;
int r;
@ -313,13 +324,17 @@ static int context_set_path(Context *c, int rfd, const char *s, const char *sour
if (*dest || !s)
return 0;
if (rfd >= 0)
r = chaseat(rfd, s, CHASE_AT_RESOLVE_IN_ROOT, &p, /* ret_fd = */ NULL);
else
r = chase(s, /* root = */ NULL, 0, &p, /* ret_fd = */ NULL);
if (r < 0)
return log_warning_errno(r, "Failed to chase path %s for %s specified via %s, ignoring: %m",
s, name, source);
if (c->rfd >= 0) {
r = chaseat(c->rfd, s, CHASE_AT_RESOLVE_IN_ROOT, &p, /* ret_fd = */ NULL);
if (r < 0)
return log_warning_errno(r, "Failed to chase path %s for %s specified via %s, ignoring: %m",
s, name, source);
} else {
r = path_make_absolute_cwd(s, &p);
if (r < 0)
return log_warning_errno(r, "Failed to make path '%s' for %s specified via %s absolute, ignoring: %m",
s, name, source);
}
log_debug("%s (%s) set via %s.", name, p, source);
@ -329,21 +344,20 @@ static int context_set_path(Context *c, int rfd, const char *s, const char *sour
static int context_set_boot_root(Context *c, const char *s, const char *source) {
assert(c);
return context_set_path(c, c->rfd, s, source, "BOOT_ROOT", &c->boot_root);
return context_set_path(c, s, source, "BOOT_ROOT", &c->boot_root);
}
static int context_set_conf_root(Context *c, const char *s, const char *source) {
assert(c);
return context_set_path(c, c->rfd, s, source, "CONF_ROOT", &c->conf_root);
return context_set_path(c, s, source, "CONF_ROOT", &c->conf_root);
}
static int context_set_kernel(Context *c, const char *s) {
assert(c);
/* The path specified via command line should be relative to CWD. */
return context_set_path(c, AT_FDCWD, s, "command line", "kernel image file", &c->kernel);
return context_set_path(c, s, "command line", "kernel image file", &c->kernel);
}
static int context_set_path_strv(Context *c, int rfd, char* const* strv, const char *source, const char *name, char ***dest) {
static int context_set_path_strv(Context *c, char* const* strv, const char *source, const char *name, char ***dest) {
_cleanup_strv_free_ char **w = NULL;
int r;
@ -358,14 +372,17 @@ static int context_set_path_strv(Context *c, int rfd, char* const* strv, const c
STRV_FOREACH(s, strv) {
char *p;
if (rfd >= 0)
r = chaseat(rfd, *s, CHASE_AT_RESOLVE_IN_ROOT, &p, /* ret_fd = */ NULL);
else
r = chase(*s, /* root = */ NULL, 0, &p, /* ret_fd = */ NULL);
if (r < 0)
return log_warning_errno(r, "Failed to chase path %s for %s specified via %s: %m",
*s, name, source);
if (c->rfd >= 0) {
r = chaseat(c->rfd, *s, CHASE_AT_RESOLVE_IN_ROOT, &p, /* ret_fd = */ NULL);
if (r < 0)
return log_warning_errno(r, "Failed to chase path %s for %s specified via %s: %m",
*s, name, source);
} else {
r = path_make_absolute_cwd(*s, &p);
if (r < 0)
return log_warning_errno(r, "Failed to make path '%s' for %s specified via %s absolute, ignoring: %m",
*s, name, source);
}
r = strv_consume(&w, p);
if (r < 0)
return log_oom();
@ -392,12 +409,12 @@ static int context_set_plugins(Context *c, const char *s, const char *source) {
if (!v)
return log_oom();
return context_set_path_strv(c, c->rfd, v, source, "plugins", &c->plugins);
return context_set_path_strv(c, v, source, "plugins", &c->plugins);
}
static int context_set_initrds(Context *c, char* const* strv) {
assert(c);
return context_set_path_strv(c, AT_FDCWD, strv, "command line", "initrds", &c->initrds);
return context_set_path_strv(c, strv, "command line", "initrds", &c->initrds);
}
static int context_load_environment(Context *c) {
@ -641,9 +658,15 @@ static int context_ensure_boot_root(Context *c) {
return r;
/* If all else fails, use /boot. */
r = chaseat(c->rfd, "/boot", CHASE_AT_RESOLVE_IN_ROOT, &c->boot_root, /* ret_fd = */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to chase '/boot': %m");
if (c->rfd >= 0) {
r = chaseat(c->rfd, "/boot", CHASE_AT_RESOLVE_IN_ROOT, &c->boot_root, /* ret_fd = */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to chase '/boot': %m");
} else {
c->boot_root = strdup("/boot");
if (!c->boot_root)
return log_oom();
}
log_debug("KERNEL_INSTALL_BOOT_ROOT autodetection yielded no candidates, using \"%s\".", c->boot_root);
return 0;
@ -1667,7 +1690,7 @@ static int run(int argc, char* argv[]) {
{}
};
_cleanup_(context_done) Context c = {
.rfd = -EBADF,
.rfd = AT_FDCWD,
.action = _ACTION_INVALID,
.kernel_image_type = KERNEL_IMAGE_TYPE_UNKNOWN,
.layout = _LAYOUT_INVALID,