|
|
9fc0f6 |
From 022406c6dcaa5e9201a30b95f3e86328739e3892 Mon Sep 17 00:00:00 2001
|
|
|
9fc0f6 |
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
|
|
9fc0f6 |
Date: Thu, 24 Apr 2014 01:44:10 -0400
|
|
|
9fc0f6 |
Subject: [PATCH] Make systemctl --root look for files in the proper places
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
Running systemctl enable/disable/set-default/... with the --root
|
|
|
9fc0f6 |
option under strace reveals that it accessed various files and
|
|
|
9fc0f6 |
directories in the main fs, and not underneath the specified root.
|
|
|
9fc0f6 |
This can lead to correct results only when the layout and
|
|
|
9fc0f6 |
configuration in the container are identical, which often is not the
|
|
|
9fc0f6 |
case. Fix this by adding the specified root to all file access
|
|
|
9fc0f6 |
operations.
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
This patch does not handle some corner cases: symlinks which point
|
|
|
9fc0f6 |
outside of the specified root might be interpreted differently than
|
|
|
9fc0f6 |
they would be by the kernel if the specified root was the real root.
|
|
|
9fc0f6 |
But systemctl does not create such symlinks by itself, and I think
|
|
|
9fc0f6 |
this is enough of a corner case not to be worth the additional
|
|
|
9fc0f6 |
complexity of reimplementing link chasing in systemd.
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
Also, simplify the code in a few places and remove an hypothetical
|
|
|
9fc0f6 |
memory leak on error.
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
Conflicts:
|
|
|
9fc0f6 |
TODO
|
|
|
9fc0f6 |
src/shared/install.c
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
(cherry picked from commit 12ed81d9c88406234c20e9261ae8c8b992d8bc4d)
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
Related: #1111199
|
|
|
9fc0f6 |
---
|
|
|
9fc0f6 |
src/core/manager.c | 2 ++
|
|
|
9fc0f6 |
src/shared/install.c | 34 +++++++++++++++++++++-----------
|
|
|
9fc0f6 |
src/shared/path-lookup.c | 12 ++++--------
|
|
|
9fc0f6 |
src/shared/path-lookup.h | 8 +++++++-
|
|
|
9fc0f6 |
src/shared/path-util.c | 49 ++++++++++++++++++++++++++++++++++++-----------
|
|
|
9fc0f6 |
src/systemctl/systemctl.c | 2 +-
|
|
|
9fc0f6 |
6 files changed, 75 insertions(+), 32 deletions(-)
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
|
9fc0f6 |
index 57a88b0..a2810b4 100644
|
|
|
9fc0f6 |
--- a/src/core/manager.c
|
|
|
9fc0f6 |
+++ b/src/core/manager.c
|
|
|
9fc0f6 |
@@ -891,6 +891,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
r = lookup_paths_init(
|
|
|
9fc0f6 |
&m->lookup_paths, m->running_as, true,
|
|
|
9fc0f6 |
+ NULL,
|
|
|
9fc0f6 |
m->generator_unit_path,
|
|
|
9fc0f6 |
m->generator_unit_path_early,
|
|
|
9fc0f6 |
m->generator_unit_path_late);
|
|
|
9fc0f6 |
@@ -2383,6 +2384,7 @@ int manager_reload(Manager *m) {
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
q = lookup_paths_init(
|
|
|
9fc0f6 |
&m->lookup_paths, m->running_as, true,
|
|
|
9fc0f6 |
+ NULL,
|
|
|
9fc0f6 |
m->generator_unit_path,
|
|
|
9fc0f6 |
m->generator_unit_path_early,
|
|
|
9fc0f6 |
m->generator_unit_path_late);
|
|
|
9fc0f6 |
diff --git a/src/shared/install.c b/src/shared/install.c
|
|
|
9fc0f6 |
index b9c85b7..672dcc2 100644
|
|
|
9fc0f6 |
--- a/src/shared/install.c
|
|
|
9fc0f6 |
+++ b/src/shared/install.c
|
|
|
9fc0f6 |
@@ -47,7 +47,9 @@ typedef struct {
|
|
|
9fc0f6 |
#define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free)
|
|
|
9fc0f6 |
#define _cleanup_install_context_done_ _cleanup_(install_context_done)
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
-static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope) {
|
|
|
9fc0f6 |
+static int lookup_paths_init_from_scope(LookupPaths *paths,
|
|
|
9fc0f6 |
+ UnitFileScope scope,
|
|
|
9fc0f6 |
+ const char *root_dir) {
|
|
|
9fc0f6 |
assert(paths);
|
|
|
9fc0f6 |
assert(scope >= 0);
|
|
|
9fc0f6 |
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
@@ -57,6 +59,7 @@ static int lookup_paths_init_from_scope(LookupPaths *paths, UnitFileScope scope)
|
|
|
9fc0f6 |
return lookup_paths_init(paths,
|
|
|
9fc0f6 |
scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
|
|
|
9fc0f6 |
scope == UNIT_FILE_USER,
|
|
|
9fc0f6 |
+ root_dir,
|
|
|
9fc0f6 |
NULL, NULL, NULL);
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -705,7 +708,7 @@ int unit_file_link(
|
|
|
9fc0f6 |
assert(scope >= 0);
|
|
|
9fc0f6 |
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1476,7 +1479,7 @@ int unit_file_enable(
|
|
|
9fc0f6 |
assert(scope >= 0);
|
|
|
9fc0f6 |
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1516,7 +1519,7 @@ int unit_file_disable(
|
|
|
9fc0f6 |
assert(scope >= 0);
|
|
|
9fc0f6 |
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1578,7 +1581,7 @@ int unit_file_set_default(
|
|
|
9fc0f6 |
if (unit_name_to_type(file) != UNIT_TARGET)
|
|
|
9fc0f6 |
return -EINVAL;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1613,7 +1616,11 @@ int unit_file_get_default(
|
|
|
9fc0f6 |
char **p;
|
|
|
9fc0f6 |
int r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ assert(scope >= 0);
|
|
|
9fc0f6 |
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
+ assert(name);
|
|
|
9fc0f6 |
+
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1665,12 +1672,13 @@ UnitFileState unit_file_get_state(
|
|
|
9fc0f6 |
if (!unit_name_is_valid(name, true))
|
|
|
9fc0f6 |
return -EINVAL;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
STRV_FOREACH(i, paths.unit_path) {
|
|
|
9fc0f6 |
struct stat st;
|
|
|
9fc0f6 |
+ char *partial;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
free(path);
|
|
|
9fc0f6 |
path = NULL;
|
|
|
9fc0f6 |
@@ -1679,10 +1687,14 @@ UnitFileState unit_file_get_state(
|
|
|
9fc0f6 |
asprintf(&path, "%s/%s/%s", root_dir, *i, name);
|
|
|
9fc0f6 |
else
|
|
|
9fc0f6 |
asprintf(&path, "%s/%s", *i, name);
|
|
|
9fc0f6 |
-
|
|
|
9fc0f6 |
if (!path)
|
|
|
9fc0f6 |
return -ENOMEM;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
+ if (root_dir)
|
|
|
9fc0f6 |
+ partial = path + strlen(root_dir) + 1;
|
|
|
9fc0f6 |
+ else
|
|
|
9fc0f6 |
+ partial = path;
|
|
|
9fc0f6 |
+
|
|
|
9fc0f6 |
/*
|
|
|
9fc0f6 |
* Search for a unit file in our default paths, to
|
|
|
9fc0f6 |
* be sure, that there are no broken symlinks.
|
|
|
9fc0f6 |
@@ -1714,7 +1726,7 @@ UnitFileState unit_file_get_state(
|
|
|
9fc0f6 |
else if (r > 0)
|
|
|
9fc0f6 |
return state;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = unit_file_can_install(&paths, root_dir, path, true);
|
|
|
9fc0f6 |
+ r = unit_file_can_install(&paths, root_dir, partial, true);
|
|
|
9fc0f6 |
if (r < 0 && errno != ENOENT)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
else if (r > 0)
|
|
|
9fc0f6 |
@@ -1822,7 +1834,7 @@ int unit_file_preset(
|
|
|
9fc0f6 |
assert(scope >= 0);
|
|
|
9fc0f6 |
assert(scope < _UNIT_FILE_SCOPE_MAX);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
@@ -1891,7 +1903,7 @@ int unit_file_get_list(
|
|
|
9fc0f6 |
if (root_dir && scope != UNIT_FILE_SYSTEM)
|
|
|
9fc0f6 |
return -EINVAL;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init_from_scope(&paths, scope);
|
|
|
9fc0f6 |
+ r = lookup_paths_init_from_scope(&paths, scope, root_dir);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c
|
|
|
9fc0f6 |
index 03c1380..b62f302 100644
|
|
|
9fc0f6 |
--- a/src/shared/path-lookup.c
|
|
|
9fc0f6 |
+++ b/src/shared/path-lookup.c
|
|
|
9fc0f6 |
@@ -239,6 +239,7 @@ int lookup_paths_init(
|
|
|
9fc0f6 |
LookupPaths *p,
|
|
|
9fc0f6 |
SystemdRunningAs running_as,
|
|
|
9fc0f6 |
bool personal,
|
|
|
9fc0f6 |
+ const char *root_dir,
|
|
|
9fc0f6 |
const char *generator,
|
|
|
9fc0f6 |
const char *generator_early,
|
|
|
9fc0f6 |
const char *generator_late) {
|
|
|
9fc0f6 |
@@ -316,11 +317,9 @@ int lookup_paths_init(
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- if (!path_strv_canonicalize_absolute(p->unit_path, NULL))
|
|
|
9fc0f6 |
+ if (!path_strv_canonicalize_absolute_uniq(p->unit_path, root_dir))
|
|
|
9fc0f6 |
return -ENOMEM;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- strv_uniq(p->unit_path);
|
|
|
9fc0f6 |
-
|
|
|
9fc0f6 |
if (!strv_isempty(p->unit_path)) {
|
|
|
9fc0f6 |
_cleanup_free_ char *t = strv_join(p->unit_path, "\n\t");
|
|
|
9fc0f6 |
if (!t)
|
|
|
9fc0f6 |
@@ -372,15 +371,12 @@ int lookup_paths_init(
|
|
|
9fc0f6 |
return -ENOMEM;
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- if (!path_strv_canonicalize_absolute(p->sysvinit_path, NULL))
|
|
|
9fc0f6 |
+ if (!path_strv_canonicalize_absolute_uniq(p->sysvinit_path, root_dir))
|
|
|
9fc0f6 |
return -ENOMEM;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- if (!path_strv_canonicalize_absolute(p->sysvrcnd_path, NULL))
|
|
|
9fc0f6 |
+ if (!path_strv_canonicalize_absolute_uniq(p->sysvrcnd_path, root_dir))
|
|
|
9fc0f6 |
return -ENOMEM;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- strv_uniq(p->sysvinit_path);
|
|
|
9fc0f6 |
- strv_uniq(p->sysvrcnd_path);
|
|
|
9fc0f6 |
-
|
|
|
9fc0f6 |
if (!strv_isempty(p->sysvinit_path)) {
|
|
|
9fc0f6 |
_cleanup_free_ char *t = strv_join(p->sysvinit_path, "\n\t");
|
|
|
9fc0f6 |
if (!t)
|
|
|
9fc0f6 |
diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h
|
|
|
9fc0f6 |
index 9dee85f..0db9bfb 100644
|
|
|
9fc0f6 |
--- a/src/shared/path-lookup.h
|
|
|
9fc0f6 |
+++ b/src/shared/path-lookup.h
|
|
|
9fc0f6 |
@@ -41,5 +41,11 @@ SystemdRunningAs systemd_running_as_from_string(const char *s) _pure_;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
int user_config_home(char **config_home);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
-int lookup_paths_init(LookupPaths *p, SystemdRunningAs running_as, bool personal, const char *generator, const char *generator_early, const char *generator_late);
|
|
|
9fc0f6 |
+int lookup_paths_init(LookupPaths *p,
|
|
|
9fc0f6 |
+ SystemdRunningAs running_as,
|
|
|
9fc0f6 |
+ bool personal,
|
|
|
9fc0f6 |
+ const char *root_dir,
|
|
|
9fc0f6 |
+ const char *generator,
|
|
|
9fc0f6 |
+ const char *generator_early,
|
|
|
9fc0f6 |
+ const char *generator_late);
|
|
|
9fc0f6 |
void lookup_paths_free(LookupPaths *p);
|
|
|
9fc0f6 |
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
|
|
|
9fc0f6 |
index de291a5..0aa5d61 100644
|
|
|
9fc0f6 |
--- a/src/shared/path-util.c
|
|
|
9fc0f6 |
+++ b/src/shared/path-util.c
|
|
|
9fc0f6 |
@@ -179,36 +179,63 @@ char **path_strv_canonicalize_absolute(char **l, const char *prefix) {
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
STRV_FOREACH(s, l) {
|
|
|
9fc0f6 |
char *t, *u;
|
|
|
9fc0f6 |
+ _cleanup_free_ char *orig = NULL;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- if (!path_is_absolute(*s))
|
|
|
9fc0f6 |
+ if (!path_is_absolute(*s)) {
|
|
|
9fc0f6 |
+ free(*s);
|
|
|
9fc0f6 |
continue;
|
|
|
9fc0f6 |
+ }
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
if (prefix) {
|
|
|
9fc0f6 |
- t = strappend(prefix, *s);
|
|
|
9fc0f6 |
- free(*s);
|
|
|
9fc0f6 |
- *s = NULL;
|
|
|
9fc0f6 |
-
|
|
|
9fc0f6 |
+ orig = *s;
|
|
|
9fc0f6 |
+ t = strappend(prefix, orig);
|
|
|
9fc0f6 |
if (!t) {
|
|
|
9fc0f6 |
enomem = true;
|
|
|
9fc0f6 |
continue;
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
- } else {
|
|
|
9fc0f6 |
+ } else
|
|
|
9fc0f6 |
t = *s;
|
|
|
9fc0f6 |
- *s = NULL;
|
|
|
9fc0f6 |
- }
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
errno = 0;
|
|
|
9fc0f6 |
u = canonicalize_file_name(t);
|
|
|
9fc0f6 |
if (!u) {
|
|
|
9fc0f6 |
- if (errno == ENOENT)
|
|
|
9fc0f6 |
- u = t;
|
|
|
9fc0f6 |
- else {
|
|
|
9fc0f6 |
+ if (errno == ENOENT) {
|
|
|
9fc0f6 |
+ if (prefix) {
|
|
|
9fc0f6 |
+ u = orig;
|
|
|
9fc0f6 |
+ orig = NULL;
|
|
|
9fc0f6 |
+ free(t);
|
|
|
9fc0f6 |
+ } else
|
|
|
9fc0f6 |
+ u = t;
|
|
|
9fc0f6 |
+ } else {
|
|
|
9fc0f6 |
free(t);
|
|
|
9fc0f6 |
if (errno == ENOMEM || errno == 0)
|
|
|
9fc0f6 |
enomem = true;
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
continue;
|
|
|
9fc0f6 |
}
|
|
|
9fc0f6 |
+ } else if (prefix) {
|
|
|
9fc0f6 |
+ char *x;
|
|
|
9fc0f6 |
+
|
|
|
9fc0f6 |
+ free(t);
|
|
|
9fc0f6 |
+ x = path_startswith(u, prefix);
|
|
|
9fc0f6 |
+ if (x) {
|
|
|
9fc0f6 |
+ /* restore the slash if it was lost */
|
|
|
9fc0f6 |
+ if (!startswith(x, "/"))
|
|
|
9fc0f6 |
+ *(--x) = '/';
|
|
|
9fc0f6 |
+
|
|
|
9fc0f6 |
+ t = strdup(x);
|
|
|
9fc0f6 |
+ free(u);
|
|
|
9fc0f6 |
+ if (!t) {
|
|
|
9fc0f6 |
+ enomem = true;
|
|
|
9fc0f6 |
+ continue;
|
|
|
9fc0f6 |
+ }
|
|
|
9fc0f6 |
+ u = t;
|
|
|
9fc0f6 |
+ } else {
|
|
|
9fc0f6 |
+ /* canonicalized path goes outside of
|
|
|
9fc0f6 |
+ * prefix, keep the original path instead */
|
|
|
9fc0f6 |
+ u = orig;
|
|
|
9fc0f6 |
+ orig = NULL;
|
|
|
9fc0f6 |
+ }
|
|
|
9fc0f6 |
} else
|
|
|
9fc0f6 |
free(t);
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
|
|
9fc0f6 |
index 1ca4fd3..1cbcd20 100644
|
|
|
9fc0f6 |
--- a/src/systemctl/systemctl.c
|
|
|
9fc0f6 |
+++ b/src/systemctl/systemctl.c
|
|
|
9fc0f6 |
@@ -4258,7 +4258,7 @@ static int enable_sysv_units(const char *verb, char **args) {
|
|
|
9fc0f6 |
/* Processes all SysV units, and reshuffles the array so that
|
|
|
9fc0f6 |
* afterwards only the native units remain */
|
|
|
9fc0f6 |
|
|
|
9fc0f6 |
- r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
|
|
|
9fc0f6 |
+ r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
|
|
|
9fc0f6 |
if (r < 0)
|
|
|
9fc0f6 |
return r;
|
|
|
9fc0f6 |
|