From 317cd27afb80161f4136d2c6e6f4d1685226dacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 4 Feb 2017 22:36:17 -0500 Subject: [PATCH] core/load-dropin: add more sanity checks on .wants/.requires symlinks Feb 04 22:35:42 systemd[1462]: foo.service: Wants dependency dropin /home/zbyszek/.config/systemd/user/foo.service.wants/diffname.service target ../barbar.service has different name Feb 04 22:35:42 systemd[1462]: foo.service: Wants dependency dropin /home/zbyszek/.config/systemd/user/foo.service.wants/wrongname is not a valid unit name, ignoring --- src/core/load-dropin.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c index a43b6540ff..ff3636149a 100644 --- a/src/core/load-dropin.c +++ b/src/core/load-dropin.c @@ -19,14 +19,37 @@ #include "conf-parser.h" +#include "fs-util.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" #include "stat-util.h" +#include "string-util.h" #include "strv.h" #include "unit-name.h" #include "unit.h" +static bool unit_name_compatible(const char *a, const char *b) { + _cleanup_free_ char *prefix = NULL; + int r; + + /* the straightforward case: the symlink name matches the target */ + if (streq(a, b)) + return true; + + r = unit_name_template(a, &prefix); + if (r < 0) { + log_oom(); + return true; + } + + /* an instance name points to a target that is just the template name */ + if (streq(prefix, b)) + return true; + + return false; +} + static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suffix) { _cleanup_strv_free_ char **paths = NULL; char **p; @@ -44,6 +67,7 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff STRV_FOREACH(p, paths) { const char *entry; + _cleanup_free_ char *target = NULL; entry = basename(*p); @@ -66,7 +90,23 @@ static int process_deps(Unit *u, UnitDependency dependency, const char *dir_suff continue; } - /* TODO: add more checks on the symlink name and target here */ + if (!unit_name_is_valid(entry, UNIT_NAME_ANY)) { + log_unit_warning(u, "%s dependency dropin %s is not a valid unit name, ignoring.", + unit_dependency_to_string(dependency), *p); + continue; + } + + r = readlink_malloc(*p, &target); + if (r < 0) { + log_unit_warning_errno(u, r, "readlink(\"%s\") failed, ignoring: %m", *p); + continue; + } + + /* We don't treat this as an error, especially because we didn't check this for a + * long time. Nevertheless, we warn, because such mismatch can be mighty confusing. */ + if (!unit_name_compatible(entry, basename(target))) + log_unit_warning(u, "%s dependency dropin %s target %s has different name", + unit_dependency_to_string(dependency), *p, target); r = unit_add_dependency_by_name(u, dependency, entry, *p, true); if (r < 0)