X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fexecute.c;h=1413c9110ee71dccdebb6eddc4d477e215755981;hb=4beaf24f416e33840a974c18c34b56084d2b978a;hp=6e2b5e48a01c7be317ba292392dd0316656a17fa;hpb=ac0930c892bc7979b4c9bc2a52e5e844650b025d;p=elogind.git diff --git a/src/core/execute.c b/src/core/execute.c index 6e2b5e48a..1413c9110 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef HAVE_PAM #include @@ -50,6 +51,7 @@ #include "capability.h" #include "util.h" #include "log.h" +#include "sd-messages.h" #include "ioprio.h" #include "securebits.h" #include "cgroup.h" @@ -955,7 +957,7 @@ static int apply_seccomp(uint32_t *syscall_filter) { for (i = 0, n = 0; i < syscall_max(); i++) if (syscall_filter[i >> 4] & (1 << (i & 31))) { struct sock_filter item[] = { - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) }; @@ -999,7 +1001,7 @@ int exec_spawn(ExecCommand *command, int r; char *line; int socket_fd; - char **files_env = NULL; + char _cleanup_strv_free_ **files_env = NULL; assert(command); assert(context); @@ -1020,8 +1022,13 @@ int exec_spawn(ExecCommand *command, } else socket_fd = -1; - if ((r = exec_context_load_environment(context, &files_env)) < 0) { - log_error("Failed to load environment files: %s", strerror(-r)); + r = exec_context_load_environment(context, &files_env); + if (r < 0) { + log_struct_unit(LOG_ERR, + unit_id, + "MESSAGE=Failed to load environment files: %s", strerror(-r), + "ERRNO=%d", -r, + NULL); return r; } @@ -1029,24 +1036,24 @@ int exec_spawn(ExecCommand *command, argv = command->argv; line = exec_command_line(argv); - if (!line) { - r = -ENOMEM; - goto fail_parent; - } + if (!line) + return log_oom(); - log_debug("About to execute: %s", line); + log_struct_unit(LOG_DEBUG, + unit_id, + "MESSAGE=About to execute %s", line, + NULL); free(line); r = cgroup_bonding_realize_list(cgroup_bondings); if (r < 0) - goto fail_parent; + return r; cgroup_attribute_apply_list(cgroup_attributes, cgroup_bondings); - if ((pid = fork()) < 0) { - r = -errno; - goto fail_parent; - } + pid = fork(); + if (pid < 0) + return -errno; if (pid == 0) { int i, err; @@ -1054,7 +1061,8 @@ int exec_spawn(ExecCommand *command, const char *username = NULL, *home = NULL; uid_t uid = (uid_t) -1; gid_t gid = (gid_t) -1; - char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; + char _cleanup_strv_free_ **our_env = NULL, **pam_env = NULL, + **final_env = NULL, **final_argv = NULL; unsigned n_env = 0; bool set_access = false; @@ -1283,7 +1291,7 @@ int exec_spawn(ExecCommand *command, umask(context->umask); #ifdef HAVE_PAM - if (context->pam_name && username) { + if (apply_permissions && context->pam_name && username) { err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds); if (err < 0) { r = EXIT_PAM; @@ -1331,8 +1339,7 @@ int exec_spawn(ExecCommand *command, goto fail_child; } } else { - - char *d; + char _cleanup_free_ *d = NULL; if (asprintf(&d, "%s/%s", context->root_directory ? context->root_directory : "", @@ -1344,12 +1351,9 @@ int exec_spawn(ExecCommand *command, if (chdir(d) < 0) { err = -errno; - free(d); r = EXIT_CHDIR; goto fail_child; } - - free(d); } /* We repeat the fd closing here, to make sure that @@ -1495,21 +1499,24 @@ int exec_spawn(ExecCommand *command, fail_child: if (r != 0) { log_open(); - log_warning("Failed at step %s spawning %s: %s", - exit_status_to_string(r, EXIT_STATUS_SYSTEMD), - command->path, strerror(-err)); + log_struct(LOG_ERR, MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED), + "EXECUTABLE=%s", command->path, + "MESSAGE=Failed at step %s spawning %s: %s", + exit_status_to_string(r, EXIT_STATUS_SYSTEMD), + command->path, strerror(-err), + "ERRNO=%d", -err, + NULL); + log_close(); } - strv_free(our_env); - strv_free(final_env); - strv_free(pam_env); - strv_free(files_env); - strv_free(final_argv); - _exit(r); } - strv_free(files_env); + log_struct_unit(LOG_DEBUG, + unit_id, + "MESSAGE=Forked %s as %lu", + command->path, (unsigned long) pid, + NULL); /* We add the new process to the cgroup both in the child (so * that we can be sure that no user code is ever executed @@ -1519,17 +1526,10 @@ int exec_spawn(ExecCommand *command, if (cgroup_bondings) cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix); - log_debug("Forked %s as %lu", command->path, (unsigned long) pid); - exec_status_start(&command->exec_status, pid); *ret = pid; return 0; - -fail_parent: - strv_free(files_env); - - return r; } void exec_context_init(ExecContext *c) { @@ -1658,6 +1658,8 @@ int exec_context_load_environment(const ExecContext *c, char ***l) { int k; bool ignore = false; char **p; + glob_t pglob; + int count, n; fn = *i; @@ -1675,29 +1677,55 @@ int exec_context_load_environment(const ExecContext *c, char ***l) { return -EINVAL; } - if ((k = load_env_file(fn, &p)) < 0) { + /* Filename supports globbing, take all matching files */ + zero(pglob); + errno = 0; + if (glob(fn, 0, NULL, &pglob) != 0) { + globfree(&pglob); + if (ignore) + continue; + strv_free(r); + return errno ? -errno : -EINVAL; + } + count = pglob.gl_pathc; + if (count == 0) { + globfree(&pglob); if (ignore) continue; strv_free(r); - return k; + return -EINVAL; } + for (n = 0; n < count; n++) { + k = load_env_file(pglob.gl_pathv[n], &p); + if (k < 0) { + if (ignore) + continue; - if (r == NULL) - r = p; - else { - char **m; + strv_free(r); + globfree(&pglob); + return k; + } - m = strv_env_merge(2, r, p); - strv_free(r); - strv_free(p); + if (r == NULL) + r = p; + else { + char **m; + + m = strv_env_merge(2, r, p); + strv_free(r); + strv_free(p); - if (!m) - return -ENOMEM; + if (!m) { + globfree(&pglob); + return -ENOMEM; + } - r = m; + r = m; + } } + globfree(&pglob); } *l = r; @@ -1769,21 +1797,37 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { if (c->rlimit[i]) fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max); - if (c->ioprio_set) + if (c->ioprio_set) { + char *class_str; + int r; + + r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str); + if (r < 0) + class_str = NULL; fprintf(f, "%sIOSchedulingClass: %s\n" "%sIOPriority: %i\n", - prefix, ioprio_class_to_string(IOPRIO_PRIO_CLASS(c->ioprio)), + prefix, strna(class_str), prefix, (int) IOPRIO_PRIO_DATA(c->ioprio)); + free(class_str); + } - if (c->cpu_sched_set) + if (c->cpu_sched_set) { + char *policy_str; + int r; + + r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str); + if (r < 0) + policy_str = NULL; fprintf(f, "%sCPUSchedulingPolicy: %s\n" "%sCPUSchedulingPriority: %i\n" "%sCPUSchedulingResetOnFork: %s\n", - prefix, sched_policy_to_string(c->cpu_sched_policy), + prefix, strna(policy_str), prefix, c->cpu_sched_priority, prefix, yes_no(c->cpu_sched_reset_on_fork)); + free(policy_str); + } if (c->cpuset) { fprintf(f, "%sCPUAffinity:", prefix); @@ -1818,12 +1862,26 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL || c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE || c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL || - c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) + c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) { + char *fac_str, *lvl_str; + int r; + + r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str); + if (r < 0) + fac_str = NULL; + + r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str); + if (r < 0) + lvl_str = NULL; + fprintf(f, "%sSyslogFacility: %s\n" "%sSyslogLevel: %s\n", - prefix, log_facility_unshifted_to_string(c->syslog_priority >> 3), - prefix, log_level_to_string(LOG_PRI(c->syslog_priority))); + prefix, strna(fac_str), + prefix, strna(lvl_str)); + free(lvl_str); + free(fac_str); + } if (c->capabilities) { char *t;