X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fexecute.c;h=ca807dc8cb2fa86ff9b2afbba8dc9ecc70d88fe8;hb=6a3f892a23db71544d0439355f96c44350dafa8f;hp=9de6e8726f2c42ac05e6a855cc29dadac13016d0;hpb=f513e420c8b1a1d4c13092cd378f048b69793497;p=elogind.git diff --git a/src/core/execute.c b/src/core/execute.c index 9de6e8726..ca807dc8c 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -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; }