From 13dcc96ffb02041018f15e6fff3979ff933ca624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 30 Aug 2019 13:52:33 +0200 Subject: [PATCH 1/3] docs: describe valid unit names in systemd.unit(5) --- man/systemd.unit.xml | 26 +++++++++++++++++--------- src/test/test-unit-name.c | 3 +++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 8307be1d33..acb09d005d 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -104,16 +104,24 @@ systemd.scope5. - Unit files are loaded from a set of paths determined during - compilation, described in the next section. + Unit files are loaded from a set of paths determined during compilation, described in the next + section. - Unit files can be parameterized by a single argument called the "instance name". The unit - is then constructed based on a "template file" which serves as the definition of multiple - services or other units. A template unit must have a single @ at the end of - the name (right before the type suffix). The name of the full unit is formed by inserting the - instance name between @ and the unit type suffix. In the unit file itself, - the instance parameter may be referred to using %i and other specifiers, see - below. + Valid unit names consist of a "name prefix" and a dot and a suffix specifying the unit type. The + "unit prefix" must consist of one or more valid characters (ASCII letters, digits, :, + -, _, ., and \). The total + length of the unit name including the suffix must not exceed 256 characters. The type suffix must be one + of .service, .socket, .device, + .mount, .automount, .swap, + .target, .path, .timer, + .slice, or .scope. + + Units names can be parameterized by a single argument called the "instance name". The unit is then + constructed based on a "template file" which serves as the definition of multiple services or other + units. A template unit must have a single @ at the end of the name (right before the + type suffix). The name of the full unit is formed by inserting the instance name between + @ and the unit type suffix. In the unit file itself, the instance parameter may be + referred to using %i and other specifiers, see below. Unit files may contain additional options on top of those listed here. If systemd encounters an unknown option, it will diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index 7fe732cf2f..25c649828e 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -50,6 +50,9 @@ static void test_unit_name_is_valid(void) { assert_se(!unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE)); assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_TEMPLATE)); assert_se( unit_name_is_valid("foo@.service", UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)); + assert_se( unit_name_is_valid(".test.service", UNIT_NAME_PLAIN)); + assert_se( unit_name_is_valid(".test@.service", UNIT_NAME_TEMPLATE)); + assert_se( unit_name_is_valid("_strange::::.service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid(".service", UNIT_NAME_ANY)); assert_se(!unit_name_is_valid("", UNIT_NAME_ANY)); From 29a45fe5aa689fa672b7791521584791b84a28b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 30 Aug 2019 14:10:08 +0200 Subject: [PATCH 2/3] shared/unit-files: we must not filter out names starting with a dot Fixes #13380. --- src/shared/unit-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c index e15ce26940..b9b5268d0a 100644 --- a/src/shared/unit-file.c +++ b/src/shared/unit-file.c @@ -242,7 +242,7 @@ int unit_file_build_name_map( if (!lookup_paths_mtime_exclude(lp, *dir)) mtime = MAX(mtime, timespec_load(&st.st_mtim)); - FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { + FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { char *filename; _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; const char *suffix, *dst = NULL; From 890befcf47b19c9aff4d9d92ab3a1231b29770ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 30 Aug 2019 14:10:42 +0200 Subject: [PATCH 3/3] shared/unit-files: only put valid unit paths and dropin dirs in the cache --- src/basic/strv.h | 12 ++++++++++++ src/shared/unit-file.c | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/basic/strv.h b/src/basic/strv.h index e80964acd1..fbfa96a566 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -157,6 +157,18 @@ void strv_print(char **l); _found; \ }) +#define ENDSWITH_SET(p, ...) \ + ({ \ + const char *_p = (p); \ + char *_found = NULL, **_i; \ + STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ + _found = endswith(_p, *_i); \ + if (_found) \ + break; \ + } \ + _found; \ + }) + #define FOREACH_STRING(x, y, ...) \ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ x; \ diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c index b9b5268d0a..4a5f23e6c1 100644 --- a/src/shared/unit-file.c +++ b/src/shared/unit-file.c @@ -246,6 +246,15 @@ int unit_file_build_name_map( char *filename; _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; const char *suffix, *dst = NULL; + bool valid_unit_name; + + valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY); + + /* We only care about valid units and dirs with certain suffixes, let's ignore the + * rest. */ + if (!valid_unit_name && + !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d")) + continue; filename = path_join(*dir, de->d_name); if (!filename) @@ -260,7 +269,7 @@ int unit_file_build_name_map( } else _filename_free = filename; /* Make sure we free the filename. */ - if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) + if (!valid_unit_name) continue; assert_se(suffix = strrchr(de->d_name, '.'));