chiark / gitweb /
busname: add parser for bus name policies
[elogind.git] / src / core / execute.c
index 9de6e8726f2c42ac05e6a855cc29dadac13016d0..ca807dc8cb2fa86ff9b2afbba8dc9ecc70d88fe8 100644 (file)
@@ -82,6 +82,7 @@
 #include "selinux-util.h"
 #include "errno-list.h"
 #include "af-list.h"
+#include "mkdir.h"
 #include "apparmor-util.h"
 
 #ifdef HAVE_SECCOMP
@@ -1247,6 +1248,7 @@ int exec_spawn(ExecCommand *command,
                bool confirm_spawn,
                CGroupControllerMask cgroup_supported,
                const char *cgroup_path,
+               const char *runtime_prefix,
                const char *unit_id,
                usec_t watchdog_usec,
                int idle_pipe[4],
@@ -1544,6 +1546,27 @@ int exec_spawn(ExecCommand *command,
                 }
 #endif
 
+                if (!strv_isempty(context->runtime_directory) && runtime_prefix) {
+                        char **rt;
+
+                        STRV_FOREACH(rt, context->runtime_directory) {
+                                _cleanup_free_ char *p;
+
+                                p = strjoin(runtime_prefix, "/", *rt, NULL);
+                                if (!p) {
+                                        r = EXIT_RUNTIME_DIRECTORY;
+                                        err = -ENOMEM;
+                                        goto fail_child;
+                                }
+
+                                err = mkdir_safe(p, context->runtime_directory_mode, uid, gid);
+                                if (err < 0) {
+                                        r = EXIT_RUNTIME_DIRECTORY;
+                                        goto fail_child;
+                                }
+                        }
+                }
+
                 if (apply_permissions) {
                         err = enforce_groups(context, username, gid);
                         if (err < 0) {
@@ -1653,7 +1676,7 @@ int exec_spawn(ExecCommand *command,
 
                 if (apply_permissions) {
 
-                        for (i = 0; i < RLIMIT_NLIMITS; i++) {
+                        for (i = 0; i < _RLIMIT_MAX; i++) {
                                 if (!context->rlimit[i])
                                         continue;
 
@@ -1840,6 +1863,7 @@ void exec_context_init(ExecContext *c) {
         c->ignore_sigpipe = true;
         c->timer_slack_nsec = (nsec_t) -1;
         c->personality = 0xffffffffUL;
+        c->runtime_directory_mode = 0755;
 }
 
 void exec_context_done(ExecContext *c) {
@@ -1918,6 +1942,33 @@ void exec_context_done(ExecContext *c) {
 
         set_free(c->address_families);
         c->address_families = NULL;
+
+        strv_free(c->runtime_directory);
+        c->runtime_directory = NULL;
+}
+
+int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
+        char **i;
+
+        assert(c);
+
+        if (!runtime_prefix)
+                return 0;
+
+        STRV_FOREACH(i, c->runtime_directory) {
+                _cleanup_free_ char *p;
+
+                p = strjoin(runtime_prefix, "/", *i, NULL);
+                if (!p)
+                        return -ENOMEM;
+
+                /* We execute this synchronously, since we need to be
+                 * sure this is gone when we start the service
+                 * next. */
+                rm_rf_dangerous(p, false, true, false);
+        }
+
+        return 0;
 }
 
 void exec_command_done(ExecCommand *c) {
@@ -2713,6 +2764,8 @@ static void *remove_tmpdir_thread(void *p) {
 }
 
 void exec_runtime_destroy(ExecRuntime *rt) {
+        int r;
+
         if (!rt)
                 return;
 
@@ -2722,13 +2775,25 @@ void exec_runtime_destroy(ExecRuntime *rt) {
 
         if (rt->tmp_dir) {
                 log_debug("Spawning thread to nuke %s", rt->tmp_dir);
-                asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
+
+                r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
+                if (r < 0) {
+                        log_warning("Failed to nuke %s: %s", rt->tmp_dir, strerror(-r));
+                        free(rt->tmp_dir);
+                }
+
                 rt->tmp_dir = NULL;
         }
 
         if (rt->var_tmp_dir) {
                 log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
-                asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
+
+                r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
+                if (r < 0) {
+                        log_warning("Failed to nuke %s: %s", rt->var_tmp_dir, strerror(-r));
+                        free(rt->var_tmp_dir);
+                }
+
                 rt->var_tmp_dir = NULL;
         }