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.c89
1 files changed, 67 insertions, 22 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index 05dc1aaec1..26e9cd5339 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -290,10 +290,10 @@ static int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
}
static int connect_logger_as(
+ Unit *unit,
const ExecContext *context,
ExecOutput output,
const char *ident,
- const char *unit_id,
int nfd,
uid_t uid,
gid_t gid) {
@@ -329,7 +329,7 @@ static int connect_logger_as(
"%i\n"
"%i\n",
context->syslog_identifier ? context->syslog_identifier : ident,
- unit_id,
+ unit->id,
context->syslog_priority,
!!context->syslog_level_prefix,
output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
@@ -544,7 +544,7 @@ static int setup_output(
case EXEC_OUTPUT_KMSG_AND_CONSOLE:
case EXEC_OUTPUT_JOURNAL:
case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
- r = connect_logger_as(context, o, ident, unit->id, fileno, uid, gid);
+ r = connect_logger_as(unit, context, o, ident, fileno, uid, gid);
if (r < 0) {
log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
r = open_null_as(O_WRONLY, fileno);
@@ -1526,14 +1526,28 @@ static bool exec_needs_mount_namespace(
return false;
}
+static void append_socket_pair(int *array, unsigned *n, int pair[2]) {
+ assert(array);
+ assert(n);
+
+ if (!pair)
+ return;
+
+ if (pair[0] >= 0)
+ array[(*n)++] = pair[0];
+ if (pair[1] >= 0)
+ array[(*n)++] = pair[1];
+}
+
static int close_remaining_fds(
const ExecParameters *params,
ExecRuntime *runtime,
+ DynamicCreds *dcreds,
int socket_fd,
int *fds, unsigned n_fds) {
unsigned n_dont_close = 0;
- int dont_close[n_fds + 7];
+ int dont_close[n_fds + 11];
assert(params);
@@ -1551,11 +1565,14 @@ static int close_remaining_fds(
n_dont_close += n_fds;
}
- if (runtime) {
- if (runtime->netns_storage_socket[0] >= 0)
- dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
- if (runtime->netns_storage_socket[1] >= 0)
- dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
+ if (runtime)
+ append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket);
+
+ if (dcreds) {
+ if (dcreds->user)
+ append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket);
+ if (dcreds->group)
+ append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket);
}
return close_all_fds(dont_close, n_dont_close);
@@ -1567,6 +1584,7 @@ static int exec_child(
const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime,
+ DynamicCreds *dcreds,
char **argv,
int socket_fd,
int *fds, unsigned n_fds,
@@ -1617,7 +1635,7 @@ static int exec_child(
log_forget_fds();
- r = close_remaining_fds(params, runtime, socket_fd, fds, n_fds);
+ r = close_remaining_fds(params, runtime, dcreds, socket_fd, fds, n_fds);
if (r < 0) {
*exit_status = EXIT_FDS;
return r;
@@ -1650,25 +1668,48 @@ static int exec_child(
}
}
- if (context->user) {
- username = context->user;
- r = get_user_creds(&username, &uid, &gid, &home, &shell);
+ if (context->dynamic_user && dcreds) {
+
+ /* Make sure we bypass our own NSS module for any NSS checks */
+ if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) {
+ *exit_status = EXIT_USER;
+ return -errno;
+ }
+
+ r = dynamic_creds_realize(dcreds, &uid, &gid);
if (r < 0) {
*exit_status = EXIT_USER;
return r;
}
- }
- if (context->group) {
- const char *g = context->group;
+ if (uid == UID_INVALID || gid == GID_INVALID) {
+ *exit_status = EXIT_USER;
+ return -ESRCH;
+ }
- r = get_group_creds(&g, &gid);
- if (r < 0) {
- *exit_status = EXIT_GROUP;
- return r;
+ if (dcreds->user)
+ username = dcreds->user->name;
+
+ } else {
+ if (context->user) {
+ username = context->user;
+ r = get_user_creds(&username, &uid, &gid, &home, &shell);
+ if (r < 0) {
+ *exit_status = EXIT_USER;
+ return r;
+ }
}
- }
+ if (context->group) {
+ const char *g = context->group;
+
+ r = get_group_creds(&g, &gid);
+ if (r < 0) {
+ *exit_status = EXIT_GROUP;
+ return r;
+ }
+ }
+ }
/* If a socket is connected to STDIN/STDOUT/STDERR, we
* must sure to drop O_NONBLOCK */
@@ -2192,6 +2233,7 @@ int exec_spawn(Unit *unit,
const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime,
+ DynamicCreds *dcreds,
pid_t *ret) {
_cleanup_strv_free_ char **files_env = NULL;
@@ -2250,6 +2292,7 @@ int exec_spawn(Unit *unit,
context,
params,
runtime,
+ dcreds,
argv,
socket_fd,
fds, n_fds,
@@ -2723,6 +2766,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
if (c->group)
fprintf(f, "%sGroup: %s\n", prefix, c->group);
+ fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
+
if (strv_length(c->supplementary_groups) > 0) {
fprintf(f, "%sSupplementaryGroups:", prefix);
strv_fprintf(f, c->supplementary_groups);
@@ -3062,7 +3107,7 @@ int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) {
return r;
if (c->private_network && (*rt)->netns_storage_socket[0] < 0) {
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (*rt)->netns_storage_socket) < 0)
+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, (*rt)->netns_storage_socket) < 0)
return -errno;
}