core: quote each exec directory entry when serializing
Quote each serialized exec directory entry, and use extract flags compatible with config_parse_exec_directories() when deserializing. This allows paths containing spaces and escaped characters to round-trip correctly. Fixes #41853. Replaces #42686.
This commit is contained in:
@@ -1867,11 +1867,11 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
FOREACH_ARRAY(i, c->directories[dt].items, c->directories[dt].n_items) {
|
||||
_cleanup_free_ char *path_escaped = NULL;
|
||||
|
||||
path_escaped = shell_escape(i->path, ":" WHITESPACE);
|
||||
path_escaped = shell_escape(i->path, ":\"");
|
||||
if (!path_escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&value, " ", path_escaped))
|
||||
if (!strextend(&value, " \"", path_escaped))
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&value, ":", yes_no(FLAGS_SET(i->flags, EXEC_DIRECTORY_ONLY_CREATE))))
|
||||
@@ -1883,13 +1883,16 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
|
||||
STRV_FOREACH(d, i->symlinks) {
|
||||
_cleanup_free_ char *link_escaped = NULL;
|
||||
|
||||
link_escaped = shell_escape(*d, ":" WHITESPACE);
|
||||
link_escaped = shell_escape(*d, ":\"");
|
||||
if (!link_escaped)
|
||||
return log_oom_debug();
|
||||
|
||||
if (!strextend(&value, ":", link_escaped))
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
if (!strextend(&value, "\""))
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
r = serialize_item(f, key, value);
|
||||
@@ -2830,15 +2833,14 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
ExecDirectoryFlags exec_directory_flags = 0;
|
||||
const char *p;
|
||||
|
||||
/* Use EXTRACT_UNESCAPE_RELAX here, as we unescape the colons in subsequent calls */
|
||||
r = extract_first_word(&val, &tuple, WHITESPACE, EXTRACT_UNESCAPE_SEPARATORS|EXTRACT_UNESCAPE_RELAX);
|
||||
r = extract_first_word(&val, &tuple, WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
p = tuple;
|
||||
r = extract_many_words(&p, ":", EXTRACT_UNESCAPE_SEPARATORS, &path, &only_create, &read_only);
|
||||
r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS, &path, &only_create, &read_only);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r < 2)
|
||||
@@ -2866,7 +2868,7 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
|
||||
for (;;) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
|
||||
r = extract_first_word(&p, &link, ":", EXTRACT_UNESCAPE_SEPARATORS);
|
||||
r = extract_first_word(&p, &link, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
||||
@@ -1140,6 +1140,10 @@ static void test_exec_runtimedirectory(Manager *m) {
|
||||
test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
|
||||
(void) rm_rf("/run/test-exec_runtimedirectory2", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
|
||||
(void) rm_rf("/run/test-exec_runtimedirectory-escape", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
test(m, "exec-runtimedirectory@foo\\x2dv1.service", 0, CLD_EXITED);
|
||||
(void) rm_rf("/run/test-exec_runtimedirectory-escape", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
|
||||
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
|
||||
test(m, "exec-runtimedirectory-owner.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED);
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
[Unit]
|
||||
Description=Test for RuntimeDirectory (escape)
|
||||
|
||||
[Service]
|
||||
ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/backsl\ash"'
|
||||
ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/foo bar:baz\\quux"'
|
||||
ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/%I"'
|
||||
ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/%i"'
|
||||
ExecStart=bash -x -c 'test -d "%t/test-exec_runtimedirectory-escape/hoge ho:ge"'
|
||||
ExecStart=bash -x -c 'test -L "%t/test-exec_runtimedirectory-escape/foo:bar"'
|
||||
ExecStart=bash -x -c 'test "$(readlink %t/test-exec_runtimedirectory-escape/foo:bar)" = "hoge ho:ge"'
|
||||
Type=oneshot
|
||||
RuntimeDirectory=test-exec_runtimedirectory-escape/backsl\ash
|
||||
RuntimeDirectory="test-exec_runtimedirectory-escape/foo bar\:baz\\quux"
|
||||
RuntimeDirectory=test-exec_runtimedirectory-escape/%I
|
||||
RuntimeDirectory=test-exec_runtimedirectory-escape/%i
|
||||
RuntimeDirectory="test-exec_runtimedirectory-escape/hoge ho\:ge:test-exec_runtimedirectory-escape/foo\:bar"
|
||||
Reference in New Issue
Block a user