summaryrefslogtreecommitdiff
path: root/src/core/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/execute.c')
-rw-r--r--src/core/execute.c173
1 files changed, 115 insertions, 58 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index fc0edc6cfd..7dc15044b4 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -39,6 +39,7 @@
#include <linux/oom.h>
#include <sys/poll.h>
#include <linux/seccomp-bpf.h>
+#include <glob.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
@@ -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"
@@ -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(LOG_ERR,
+ "UNIT=%s", 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(LOG_DEBUG,
+ "UNIT=%s", 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;
@@ -1304,7 +1312,7 @@ int exec_spawn(ExecCommand *command,
if (strv_length(context->read_write_dirs) > 0 ||
strv_length(context->read_only_dirs) > 0 ||
strv_length(context->inaccessible_dirs) > 0 ||
- context->mount_flags != MS_SHARED ||
+ context->mount_flags != 0 ||
context->private_tmp) {
err = setup_namespace(context->read_write_dirs,
context->read_only_dirs,
@@ -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(LOG_DEBUG,
+ "UNIT=%s", 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) {
@@ -1540,7 +1540,6 @@ void exec_context_init(ExecContext *c) {
c->cpu_sched_policy = SCHED_OTHER;
c->syslog_priority = LOG_DAEMON|LOG_INFO;
c->syslog_level_prefix = true;
- c->mount_flags = MS_SHARED;
c->control_group_persistent = -1;
c->ignore_sigpipe = true;
c->timer_slack_nsec = (nsec_t) -1;
@@ -1659,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;
@@ -1676,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;
@@ -1770,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);
@@ -1819,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;