<refsect2>
<title>Type</title>
- <para>The type consists of a single letter and optionally a plus sign (<literal>+</literal>),
- exclamation mark (<literal>!</literal>), minus sign (<literal>-</literal>), equals sign
- (<literal>=</literal>) and/or tilde character (<literal>~</literal>).</para>
+ <para>The type consists of a single letter and optionally one or emore modifier characters: a plus sign
+ (<literal>+</literal>), exclamation mark (<literal>!</literal>), minus sign (<literal>-</literal>),
+ equals sign (<literal>=</literal>), tilde character (<literal>~</literal>) and/or caret
+ (<literal>^</literal>).</para>
<para>The following line types are understood:</para>
<para>If the tilde character (<literal>~</literal>) is used, the argument (i.e. 6th) column is <ulink
url="https://www.rfc-editor.org/rfc/rfc4648.html">Base64 decoded</ulink> before use. This modifier is
only supported on line types that can write file contents, i.e. <varname>f</varname>,
- <varname>f+</varname>, <varname>w</varname>. This is useful for writing arbitrary binary data
- (including newlines and NUL bytes) to files. Note that if this switch is used, the argument is not
- subject to specifier expansion, neither before nor after Base64 decoding.</para>
+ <varname>f+</varname>, <varname>w</varname>, <varname>+</varname>. This is useful for writing arbitrary
+ binary data (including newlines and NUL bytes) to files. Note that if this switch is used, the argument
+ is not subject to specifier expansion, neither before nor after Base64 decoding.</para>
+
+ <para>If the caret character (<literal>^</literal>) is used, the argument (i.e. 6th) column takes a
+ service credential name to read the argument data from. See <ulink
+ url="https://systemd.io/CREDENTIALS">System and Service Credentials</ulink> for details about the
+ credentials concept. This modifier is only supported on line types that can write file contents,
+ i.e. <varname>f</varname>, <varname>f+</varname>, <varname>w</varname>, <varname>w+</varname>. This is
+ useful for writing arbitrary files with contents sourced from elsewhere, including from VM or container
+ managers further up. If the specified credential is not set for the <command>systemd-tmpfiles</command>
+ service, the line is silently skipped. If <literal>^</literal> and <literal>~</literal> are combined
+ Base64 decoding is applied to the credential contents.</para>
<para>Note that for all line types that result in creation of any kind of file node
(i.e. <varname>f</varname>/<varname>F</varname>,
ItemArray *existing;
OrderedHashmap *h;
int r, pos;
- bool append_or_force = false, boot = false, allow_failure = false, try_replace = false, unbase64 = false;
+ bool append_or_force = false, boot = false, allow_failure = false, try_replace = false, unbase64 = false, from_cred = false;
assert(fname);
assert(line >= 1);
try_replace = true;
else if (action[pos] == '~' && !unbase64)
unbase64 = true;
+ else if (action[pos] == '^' && !from_cred)
+ from_cred = true;
else {
*invalid_config = true;
return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EBADMSG), "Unknown modifiers in command '%s'", action);
if (!should_include_path(i.path))
return 0;
- if (unbase64) {
- if (i.argument) {
- r = unbase64mem(i.argument, SIZE_MAX, &i.binary_argument, &i.binary_argument_size);
- if (r < 0)
- return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to base64 decode specified argument '%s': %m", i.argument);
- }
- } else {
+ if (!unbase64) {
+ /* Do specifier expansion except if base64 mode is enabled */
r = specifier_expansion_from_arg(specifier_table, &i);
if (r == -ENXIO)
return log_unresolvable_specifier(fname, line);
}
}
+ if (from_cred) {
+ if (!i.argument)
+ return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Reading from credential requested, but no credential name specified.");
+ if (!credential_name_valid(i.argument))
+ return log_syntax(NULL, LOG_ERR, fname, line, SYNTHETIC_ERRNO(EINVAL), "Credential name not valid: %s", i.argument);
+
+ r = read_credential(i.argument, &i.binary_argument, &i.binary_argument_size);
+ if (IN_SET(r, -ENXIO, -ENOENT)) {
+ /* Silently skip over lines that have no credentials passed */
+ log_syntax(NULL, LOG_INFO, fname, line, 0, "Credential '%s' not specified, skipping line.", i.argument);
+ return 0;
+ }
+ if (r < 0)
+ return log_error_errno(r, "Failed to read credential '%s': %m", i.argument);
+ }
+
+ /* If base64 decoding is requested, do so now */
+ if (unbase64 && item_binary_argument(&i)) {
+ _cleanup_free_ void *data = NULL;
+ size_t data_size = 0;
+
+ r = unbase64mem(item_binary_argument(&i), item_binary_argument_size(&i), &data, &data_size);
+ if (r < 0)
+ return log_syntax(NULL, LOG_ERR, fname, line, r, "Failed to base64 decode specified argument '%s': %m", i.argument);
+
+ free_and_replace(i.binary_argument, data);
+ i.binary_argument_size = data_size;
+ }
+
if (!empty_or_root(arg_root)) {
char *p;