summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
62b0023)
Running systemctl enable/disable/set-default/... with the --root
option under strace reveals that it accessed various files and
directories in the main fs, and not underneath the specified root.
This can lead to correct results only when the layout and
configuration in the container are identical, which often is not the
case. Fix this by adding the specified root to all file access
operations.
This patch does not handle some corner cases: symlinks which point
outside of the specified root might be interpreted differently than
they would be by the kernel if the specified root was the real root.
But systemctl does not create such symlinks by itself, and I think
this is enough of a corner case not to be worth the additional
complexity of reimplementing link chasing in systemd.
Also, simplify the code in a few places and remove an hypothetical
memory leak on error.
Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory. See system logs and 'systemctl status display-manager.service' for details.
Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory. See system logs and 'systemctl status display-manager.service' for details.
-* systemctl --root=container/ set-default ... is totally borked.
-
* sd_bus_unref() is broken regarding self-references and "pseudo thread-safety".
See the comment in sd_bus_unref() for more..
* sd_bus_unref() is broken regarding self-references and "pseudo thread-safety".
See the comment in sd_bus_unref() for more..
r = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
r = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
q = lookup_paths_init(
&m->lookup_paths, m->running_as, true,
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
m->generator_unit_path,
m->generator_unit_path_early,
m->generator_unit_path_late);
#define _cleanup_install_context_done_ _cleanup_(install_context_done)
#define _cleanup_install_context_done_ _cleanup_(install_context_done)
-static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
+static int lookup_paths_init_from_scope(LookupPaths *paths,
+ UnitFileScope scope,
+ const char *root_dir) {
assert(paths);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(paths);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
return lookup_paths_init(paths,
scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
scope == UNIT_FILE_USER,
return lookup_paths_init(paths,
scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
scope == UNIT_FILE_USER,
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (unit_name_to_type(file) != UNIT_TARGET)
return -EINVAL;
if (unit_name_to_type(file) != UNIT_TARGET)
return -EINVAL;
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(name);
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (!unit_name_is_valid(name, TEMPLATE_VALID))
return -EINVAL;
if (!unit_name_is_valid(name, TEMPLATE_VALID))
return -EINVAL;
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (r < 0)
return r;
STRV_FOREACH(i, paths.unit_path) {
struct stat st;
if (r < 0)
return r;
STRV_FOREACH(i, paths.unit_path) {
struct stat st;
asprintf(&path, "%s/%s/%s", root_dir, *i, name);
else
asprintf(&path, "%s/%s", *i, name);
asprintf(&path, "%s/%s/%s", root_dir, *i, name);
else
asprintf(&path, "%s/%s", *i, name);
if (!path)
return -ENOMEM;
if (!path)
return -ENOMEM;
+ if (root_dir)
+ partial = path + strlen(root_dir) + 1;
+ else
+ partial = path;
+
/*
* Search for a unit file in our default paths, to
* be sure, that there are no broken symlinks.
/*
* Search for a unit file in our default paths, to
* be sure, that there are no broken symlinks.
else if (r > 0)
return state;
else if (r > 0)
return state;
- r = unit_file_can_install(&paths, root_dir, path, true);
+ r = unit_file_can_install(&paths, root_dir, partial, true);
if (r < 0 && errno != ENOENT)
return r;
else if (r > 0)
if (r < 0 && errno != ENOENT)
return r;
else if (r > 0)
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
assert(scope >= 0);
assert(scope < _UNIT_FILE_SCOPE_MAX);
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
if (root_dir && scope != UNIT_FILE_SYSTEM)
return -EINVAL;
if (root_dir && scope != UNIT_FILE_SYSTEM)
return -EINVAL;
- r = lookup_paths_init_from_scope(&paths, scope);
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
LookupPaths *p,
SystemdRunningAs running_as,
bool personal,
LookupPaths *p,
SystemdRunningAs running_as,
bool personal,
const char *generator,
const char *generator_early,
const char *generator_late) {
const char *generator,
const char *generator_early,
const char *generator_late) {
- if (!path_strv_canonicalize_absolute(p->unit_path, NULL))
+ if (!path_strv_canonicalize_absolute_uniq(p->unit_path, root_dir))
- strv_uniq(p->unit_path);
-
if (!strv_isempty(p->unit_path)) {
_cleanup_free_ char *t = strv_join(p->unit_path, "\n\t");
if (!t)
if (!strv_isempty(p->unit_path)) {
_cleanup_free_ char *t = strv_join(p->unit_path, "\n\t");
if (!t)
- if (!path_strv_canonicalize_absolute(p->sysvinit_path, NULL))
+ if (!path_strv_canonicalize_absolute_uniq(p->sysvinit_path, root_dir))
- if (!path_strv_canonicalize_absolute(p->sysvrcnd_path, NULL))
+ if (!path_strv_canonicalize_absolute_uniq(p->sysvrcnd_path, root_dir))
- strv_uniq(p->sysvinit_path);
- strv_uniq(p->sysvrcnd_path);
-
if (!strv_isempty(p->sysvinit_path)) {
_cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t");
if (!t)
if (!strv_isempty(p->sysvinit_path)) {
_cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t");
if (!t)
int user_config_home(char **config_home);
int user_config_home(char **config_home);
-int lookup_paths_init(LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late);
+int lookup_paths_init(LookupPaths *p,
+ SystemdRunningAs running_as,
+ bool personal,
+ const char *root_dir,
+ const char *generator,
+ const char *generator_early,
+ const char *generator_late);
void lookup_paths_free(LookupPaths *p);
void lookup_paths_free(LookupPaths *p);
STRV_FOREACH(s, l) {
char *t, *u;
STRV_FOREACH(s, l) {
char *t, *u;
+ _cleanup_free_ char *orig = NULL;
- if (!path_is_absolute(*s))
+ if (!path_is_absolute(*s)) {
+ free(*s);
- t = strappend(prefix, *s);
- free(*s);
- *s = NULL;
-
+ orig = *s;
+ t = strappend(prefix, orig);
if (!t) {
enomem = true;
continue;
}
if (!t) {
enomem = true;
continue;
}
errno = 0;
u = canonicalize_file_name(t);
if (!u) {
errno = 0;
u = canonicalize_file_name(t);
if (!u) {
- if (errno == ENOENT)
- u = t;
- else {
+ if (errno == ENOENT) {
+ if (prefix) {
+ u = orig;
+ orig = NULL;
+ free(t);
+ } else
+ u = t;
+ } else {
free(t);
if (errno == ENOMEM || errno == 0)
enomem = true;
continue;
}
free(t);
if (errno == ENOMEM || errno == 0)
enomem = true;
continue;
}
+ } else if (prefix) {
+ char *x;
+
+ free(t);
+ x = path_startswith(u, prefix);
+ if (x) {
+ /* restore the slash if it was lost */
+ if (!startswith(x, "/"))
+ *(--x) = '/';
+
+ t = strdup(x);
+ free(u);
+ if (!t) {
+ enomem = true;
+ continue;
+ }
+ u = t;
+ } else {
+ /* canonicalized path goes outside of
+ * prefix, keep the original path instead */
+ u = orig;
+ orig = NULL;
+ }
/* Processes all SysV units, and reshuffles the array so that
* afterwards only the native units remain */
/* Processes all SysV units, and reshuffles the array so that
* afterwards only the native units remain */
- r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
+ r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);