]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
execute: don't fail if we create the runtime directory from two processes simultaneously 896/head
authorLennart Poettering <lennart@poettering.net>
Thu, 6 Aug 2015 11:53:15 +0000 (14:53 +0300)
committerLennart Poettering <lennart@poettering.net>
Thu, 6 Aug 2015 11:56:20 +0000 (14:56 +0300)
If a service has both ExecStart= and ExecStartPost= set with
Type=simple, then it might happen that we have two children create the
runtime directory of a service (as configured with RuntimeDirectory=) at
the same time. Previously we did this with mkdir_safe() which will
create the dir only if it is missing, but if it already exists will at
least verify the access mode and ownership to match the right values.
This is problematic in this case, since it creates and then adjusts the
settings, thus it might happen that one child creates the directory with
root owner, another one then verifies it, and only afterwards the
directory ownership is fixed by the original child, while the second
child already failed.

With this change we'll now always adjust the access mode, so that we
know that it is right. In the worst case this means we adjust the
mode/ownership even though its unnecessary, but this should have no
negative effect.

https://bugzilla.redhat.com/show_bug.cgi?id=1226509

src/core/execute.c

index 125cb0dbd488fd6b1a6580a63a29cb5715dd60aa..3820165241cb1c4e233cc33f5dc05ccdadd0727a 100644 (file)
@@ -1554,7 +1554,13 @@ static int exec_child(
                                 return -ENOMEM;
                         }
 
-                        r = mkdir_safe_label(p, context->runtime_directory_mode, uid, gid);
+                        r = mkdir_p_label(p, context->runtime_directory_mode);
+                        if (r < 0) {
+                                *exit_status = EXIT_RUNTIME_DIRECTORY;
+                                return r;
+                        }
+
+                        r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid);
                         if (r < 0) {
                                 *exit_status = EXIT_RUNTIME_DIRECTORY;
                                 return r;