core: support subdirectories in RuntimeDirectory= option
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 Jul 2017 07:30:53 +0000 (16:30 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 17 Jul 2017 07:30:53 +0000 (16:30 +0900)
man/systemd.exec.xml
src/core/execute.c
src/core/load-fragment.c

index db491b4..73d18b1 100644 (file)
       <varlistentry>
         <term><varname>RuntimeDirectory=</varname></term>
 
-        <listitem><para>Takes a list of directory names. If set, one
-        or more directories by the specified names will be created
-        below <filename>/run</filename> (for system services) or below
-        <varname>$XDG_RUNTIME_DIR</varname> (for user services) when
-        the unit is started, and removed when the unit is stopped.
-        It is possible to preserve the directories if
-        <varname>RuntimeDirectoryPreserve=</varname> is configured to
-        <option>restart</option> or <option>yes</option>. The
-        directories will have the access mode specified in
-        <varname>RuntimeDirectoryMode=</varname>, and will be owned by
-        the user and group specified in <varname>User=</varname> and
-        <varname>Group=</varname>. Use this to manage one or more
-        runtime directories of the unit and bind their lifetime to the
-        daemon runtime. The specified directory names must be
-        relative, and may not include a <literal>/</literal>, i.e.
-        must refer to simple directories to create or remove. This is
-        particularly useful for unprivileged daemons that cannot
-        create runtime directories in <filename>/run</filename> due to
-        lack of privileges, and to make sure the runtime directory is
-        cleaned up automatically after use. For runtime directories
-        that require more complex or different configuration or
-        lifetime guarantees, please consider using
-        <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
+        <listitem><para>Takes a whitespace-separated list of directory names. The specified directory names must be
+        relative, and may not include <literal>.</literal> or <literal>..</literal>. If set, one or more directories
+        including their parents by the specified names will be created below <filename>/run</filename> (for system
+        services) or below <varname>$XDG_RUNTIME_DIR</varname> (for user services) when the unit is started. The
+        lowest subdirectories are removed when the unit is stopped. It is possible to preserve the directories if
+        <varname>RuntimeDirectoryPreserve=</varname> is configured to <option>restart</option> or <option>yes</option>.
+        The lowest subdirectories will have the access mode specified in <varname>RuntimeDirectoryMode=</varname>,
+        and be owned by the user and group specified in <varname>User=</varname> and <varname>Group=</varname>.
+        This implies <varname>ReadWritePaths=</varname>, that is, the directories specified
+        in this option are accessible with the access mode specified in <varname>RuntimeDirectoryMode=</varname>
+        even if <varname>ProtectSystem=</varname> is set to <option>strict</option>.
+        Use this to manage one or more runtime directories of the unit and bind their
+        lifetime to the daemon runtime. This is particularly useful for unprivileged daemons that cannot create
+        runtime directories in <filename>/run</filename> due to lack of privileges, and to make sure the runtime
+        directory is cleaned up automatically after use. For runtime directories that require more complex or
+        different configuration or lifetime guarantees, please consider using
+        <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+        <para>Example: if a system service unit has the following,
+        <programlisting>RuntimeDirectory=foo/bar baz</programlisting>
+        the service manager creates <filename>/run/foo</filename> (if it does not exist), <filename>/run/foo/bar</filename>,
+        and <filename>/run/baz</filename>. The directories <filename>/run/foo/bar</filename> and <filename>/run/baz</filename>
+        except <filename>/run/foo</filename> are owned by the user and group specified in <varname>User=</varname> and
+        <varname>Group=</varname>, and removed when the service is stopped.
+        </para></listitem>
       </varlistentry>
 
       <varlistentry>
         <listitem><para>Specifies the access mode of the directories specified in
         <varname>RuntimeDirectory=</varname> as an octal number. Defaults to
         <constant>0755</constant>. See "Permissions" in
-        <citerefentry project='man-pages'><refentrytitle>path_resolution</refentrytitle><manvolnum>7</manvolnum></citerefentry> for a discussion of the meaning of permission bits.
+        <citerefentry project='man-pages'><refentrytitle>path_resolution</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+        for a discussion of the meaning of permission bits.
         </para></listitem>
       </varlistentry>
 
index d1d660f..fd769b2 100644 (file)
@@ -1858,6 +1858,10 @@ static int setup_runtime_directory(
                 if (!p)
                         return -ENOMEM;
 
+                r = mkdir_parents_label(p, 0755);
+                if (r < 0)
+                        return r;
+
                 r = mkdir_p_label(p, context->runtime_directory_mode);
                 if (r < 0)
                         return r;
index 15d392c..00b7f69 100644 (file)
@@ -3752,7 +3752,7 @@ int config_parse_runtime_directory(
                         continue;
                 }
 
-                if (!filename_is_valid(k)) {
+                if (!path_is_safe(k) || path_is_absolute(k)) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
                                    "Runtime directory is not valid, ignoring assignment: %s", rvalue);
                         continue;