#include <errno.h>
#include <fcntl.h>
-#include <glob.h>
-#include <grp.h>
#include <poll.h>
#include <signal.h>
-#include <string.h>
-#include <sys/capability.h>
#include <sys/eventfd.h>
+#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/shm.h>
-#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include "cap-list.h"
#include "capability-util.h"
#include "chown-recursive.h"
+#include "cgroup-setup.h"
#include "cpu-set-util.h"
#include "def.h"
#include "env-file.h"
#include "macro.h"
#include "manager.h"
#include "memory-util.h"
-#include "missing.h"
+#include "missing_fs.h"
#include "mkdir.h"
#include "namespace.h"
#include "parse-util.h"
const ExecContext *context,
const ExecParameters *params,
int socket_fd,
- int named_iofds[3]) {
+ const int named_iofds[static 3]) {
ExecInput i;
assert(context);
assert(params);
+ assert(named_iofds);
if (params->stdin_fd >= 0) {
if (dup2(params->stdin_fd, STDIN_FILENO) < 0)
const ExecParameters *params,
int fileno,
int socket_fd,
- int named_iofds[3],
+ const int named_iofds[static 3],
const char *ident,
uid_t uid,
gid_t gid,
*/
errno = 0;
ngroups_max = (int) sysconf(_SC_NGROUPS_MAX);
- if (ngroups_max <= 0) {
- if (errno > 0)
- return -errno;
- else
- return -EOPNOTSUPP; /* For all other values */
- }
+ if (ngroups_max <= 0)
+ return errno_or_else(EOPNOTSUPP);
l_gids = new(gid_t, ngroups_max);
if (!l_gids)
n = write(idle_pipe[3], "x", 1);
if (n > 0)
/* Wait for systemd to react to the signal above. */
- fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
+ (void) fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
}
idle_pipe[0] = safe_close(idle_pipe[0]);
}
if (home) {
- x = strappend("HOME=", home);
+ x = strjoin("HOME=", home);
if (!x)
return -ENOMEM;
}
if (username) {
- x = strappend("LOGNAME=", username);
+ x = strjoin("LOGNAME=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
- x = strappend("USER=", username);
+ x = strjoin("USER=", username);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
}
if (shell) {
- x = strappend("SHELL=", shell);
+ x = strjoin("SHELL=", shell);
if (!x)
return -ENOMEM;
if (!term)
term = default_term_for_tty(tty_path);
- x = strappend("TERM=", term);
+ x = strjoin("TERM=", term);
if (!x)
return -ENOMEM;
our_env[n_env++] = x;
return 0;
}
+static bool exec_directory_is_private(const ExecContext *context, ExecDirectoryType type) {
+ if (!context->dynamic_user)
+ return false;
+
+ if (type == EXEC_DIRECTORY_CONFIGURATION)
+ return false;
+
+ if (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO)
+ return false;
+
+ return true;
+}
+
static int setup_exec_directory(
const ExecContext *context,
const ExecParameters *params,
if (r < 0)
goto fail;
- if (context->dynamic_user &&
- (!IN_SET(type, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION) ||
- (type == EXEC_DIRECTORY_RUNTIME && context->runtime_directory_preserve_mode != EXEC_PRESERVE_NO))) {
+ if (exec_directory_is_private(context, type)) {
_cleanup_free_ char *private_root = NULL;
/* So, here's one extra complication when dealing with DynamicUser=1 units. In that
if (strv_isempty(context->directories[t].paths))
continue;
- if (context->dynamic_user &&
- !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION) &&
+ if (exec_directory_is_private(context, t) &&
!(context->root_directory || context->root_image)) {
char *private_root;
STRV_FOREACH(suffix, context->directories[t].paths) {
char *s, *d;
- if (context->dynamic_user &&
- !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION))
+ if (exec_directory_is_private(context, t))
s = path_join(params->prefix[t], "private", *suffix);
else
s = path_join(params->prefix[t], *suffix);
goto finish;
}
- if (context->dynamic_user &&
- !IN_SET(t, EXEC_DIRECTORY_RUNTIME, EXEC_DIRECTORY_CONFIGURATION) &&
+ if (exec_directory_is_private(context, t) &&
(context->root_directory || context->root_image))
/* When RootDirectory= or RootImage= are set, then the symbolic link to the private
* directory is not created on the root directory. So, let's bind-mount the directory
static void append_socket_pair(int *array, size_t *n, const int pair[static 2]) {
assert(array);
assert(n);
-
- if (!pair)
- return;
+ assert(pair);
if (pair[0] >= 0)
array[(*n)++] = pair[0];
STRV_FOREACH(i, c->directories[t].paths) {
char *e;
- if (t == EXEC_DIRECTORY_RUNTIME)
- e = path_join(p->prefix[t], *i);
- else
+ if (exec_directory_is_private(c, t))
e = path_join(p->prefix[t], "private", *i);
+ else
+ e = path_join(p->prefix[t], *i);
if (!e)
return -ENOMEM;
ExecRuntime *runtime,
DynamicCreds *dcreds,
int socket_fd,
- int named_iofds[3],
+ const int named_iofds[static 3],
int *fds,
size_t n_socket_fds,
size_t n_storage_fds,
}
static int exec_context_load_environment(const Unit *unit, const ExecContext *c, char ***l);
-static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[3]);
+static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]);
int exec_spawn(Unit *unit,
ExecCommand *command,
unit->manager->user_lookup_fds[1],
&exit_status);
- if (r < 0)
+ if (r < 0) {
+ const char *status =
+ exit_status_to_string(exit_status,
+ EXIT_STATUS_LIBC | EXIT_STATUS_SYSTEMD);
+
log_struct_errno(LOG_ERR, r,
"MESSAGE_ID=" SD_MESSAGE_SPAWN_FAILED_STR,
LOG_UNIT_ID(unit),
LOG_UNIT_INVOCATION_ID(unit),
LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
- exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
- command->path),
+ status, command->path),
"EXECUTABLE=%s", command->path);
+ }
_exit(exit_status);
}
c->personality = PERSONALITY_INVALID;
for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++)
c->directories[i].mode = 0755;
+ c->timeout_clean_usec = USEC_INFINITY;
c->capability_bounding_set = CAP_ALL;
assert_cc(NAMESPACE_FLAGS_INITIAL != NAMESPACE_FLAGS_ALL);
c->restrict_namespaces = NAMESPACE_FLAGS_INITIAL;
exec_context_free_log_extra_fields(c);
- c->log_rate_limit_interval_usec = 0;
- c->log_rate_limit_burst = 0;
+ c->log_ratelimit_interval_usec = 0;
+ c->log_ratelimit_burst = 0;
c->stdin_data = mfree(c->stdin_data);
c->stdin_data_size = 0;
STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) {
_cleanup_free_ char *p;
- p = path_join(runtime_prefix, *i);
+ if (exec_directory_is_private(c, EXEC_DIRECTORY_RUNTIME))
+ p = path_join(runtime_prefix, "private", *i);
+ else
+ p = path_join(runtime_prefix, *i);
if (!p)
return -ENOMEM;
}
}
-static int exec_context_named_iofds(const ExecContext *c, const ExecParameters *p, int named_iofds[static 3]) {
+static int exec_context_named_iofds(
+ const ExecContext *c,
+ const ExecParameters *p,
+ int named_iofds[static 3]) {
+
size_t i, targets;
const char* stdio_fdname[3];
size_t n_fds;
assert(c);
assert(p);
+ assert(named_iofds);
targets = (c->std_input == EXEC_INPUT_NAMED_FD) +
(c->std_output == EXEC_OUTPUT_NAMED_FD) +
}
void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
+ char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX];
ExecDirectoryType dt;
- char **e, **d;
unsigned i;
int r;
fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), *d);
}
+ fprintf(f,
+ "%sTimeoutCleanSec: %s\n",
+ prefix, format_timespan(buf_clean, sizeof(buf_clean), c->timeout_clean_usec, USEC_PER_SEC));
+
if (c->nice_set)
fprintf(f,
"%sNice: %i\n",
fprintf(f, "%sLogLevelMax: %s\n", prefix, strna(t));
}
- if (c->log_rate_limit_interval_usec > 0) {
+ if (c->log_ratelimit_interval_usec > 0) {
char buf_timespan[FORMAT_TIMESPAN_MAX];
fprintf(f,
"%sLogRateLimitIntervalSec: %s\n",
- prefix, format_timespan(buf_timespan, sizeof(buf_timespan), c->log_rate_limit_interval_usec, USEC_PER_SEC));
+ prefix, format_timespan(buf_timespan, sizeof(buf_timespan), c->log_ratelimit_interval_usec, USEC_PER_SEC));
}
- if (c->log_rate_limit_burst > 0)
- fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_rate_limit_burst);
+ if (c->log_ratelimit_burst > 0)
+ fprintf(f, "%sLogRateLimitBurst: %u\n", prefix, c->log_ratelimit_burst);
if (c->n_log_extra_fields > 0) {
size_t j;
r = strv_consume(&l, j);
if (r < 0)
return r;
+
+ /* Also remove private directories unconditionally. */
+ if (t != EXEC_DIRECTORY_CONFIGURATION) {
+ j = path_join(prefix[t], "private", *i);
+ if (!j)
+ return -ENOMEM;
+
+ r = strv_consume(&l, j);
+ if (r < 0)
+ return r;
+ }
}
}