repart: expand specifiers in MakeSymlinks= target

Previously, they were only expanded in the source part of the arguments.
No other validation is applied to the target component.
This commit is contained in:
Kai Wohlfahrt
2026-06-22 10:24:26 +02:00
parent a4f7c9589e
commit 7efb51b0e1
3 changed files with 20 additions and 8 deletions
+2 -2
View File
@@ -1176,8 +1176,8 @@
<title>Specifiers</title>
<para>Specifiers may be used in the <varname>Label=</varname>, <varname>CopyBlocks=</varname>,
<varname>CopyFiles=</varname>, <varname>MakeDirectories=</varname>, <varname>SplitName=</varname>
settings. The following expansions are understood:</para>
<varname>CopyFiles=</varname>, <varname>MakeDirectories=</varname>, <varname>MakeSymlinks=</varname>,
<varname>SplitName=</varname> settings. The following expansions are understood:</para>
<table class='specifiers'>
<title>Specifiers available</title>
<tgroup cols='3' align='left' colsep='1' rowsep='1'>
+14 -6
View File
@@ -2366,7 +2366,7 @@ static int config_parse_make_symlinks(
int r;
for (;;) {
_cleanup_free_ char *word = NULL, *path = NULL, *target = NULL, *d = NULL;
_cleanup_free_ char *word = NULL, *source = NULL, *target = NULL, *resolved_source = NULL, *resolved_target = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
@@ -2379,7 +2379,7 @@ static int config_parse_make_symlinks(
return 0;
const char *q = word;
r = extract_many_words(&q, ":", EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS, &path, &target);
r = extract_many_words(&q, ":", EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS, &source, &target);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", q);
continue;
@@ -2390,18 +2390,26 @@ static int config_parse_make_symlinks(
continue;
}
r = specifier_printf(path, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, /* userdata= */ NULL, &d);
r = specifier_printf(source, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, /* userdata= */ NULL, &resolved_source);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in Subvolumes= parameter, ignoring: %s", path);
"Failed to expand specifiers in MakeSymlinks= source, ignoring: %s", source);
continue;
}
r = path_simplify_and_warn(d, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
r = path_simplify_and_warn(resolved_source, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
if (r < 0)
continue;
r = strv_consume_pair(sv, TAKE_PTR(d), TAKE_PTR(target));
r = specifier_printf(target, PATH_MAX-1, system_and_tmp_specifier_table, arg_root, /* userdata= */ NULL, &resolved_target);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in MakeSymlinks= target, ignoring: %s", target);
continue;
}
/* Don't simplify the symlink target, preserve the exact argument including relative components */
r = strv_consume_pair(sv, TAKE_PTR(resolved_source), TAKE_PTR(resolved_target));
if (r < 0)
return log_error_errno(r, "Failed to add symlink to list: %m");
}
+4
View File
@@ -1618,6 +1618,8 @@ Type=root
MakeDirectories=/dir
MakeSymlinks=/foo:/bar
MakeSymlinks=/dir/foo:/bar
MakeSymlinks=/dir/foo-%a:/bar-%a
MakeSymlinks=/dir/bar-%a:../bar-%a
EOF
systemd-repart --offline="$OFFLINE" \
@@ -1632,6 +1634,8 @@ EOF
systemd-dissect "$imgs/zzz" -M "$imgs/mnt"
assert_eq "$(readlink "$imgs/mnt/foo")" "/bar"
assert_eq "$(readlink "$imgs/mnt/dir/foo")" "/bar"
assert_eq "$(readlink "$imgs/mnt/dir/foo-${architecture}")" "/bar-${architecture}"
assert_eq "$(readlink "$imgs/mnt/dir/bar-${architecture}")" "../bar-${architecture}"
systemd-dissect -U "$imgs/mnt"
}