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.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index 18bb421cab..4c786a2e33 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1723,11 +1723,12 @@ static int close_remaining_fds(
const ExecParameters *params,
ExecRuntime *runtime,
DynamicCreds *dcreds,
+ int user_lookup_fd,
int socket_fd,
int *fds, unsigned n_fds) {
unsigned n_dont_close = 0;
- int dont_close[n_fds + 11];
+ int dont_close[n_fds + 12];
assert(params);
@@ -1755,9 +1756,40 @@ static int close_remaining_fds(
append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket);
}
+ if (user_lookup_fd >= 0)
+ dont_close[n_dont_close++] = user_lookup_fd;
+
return close_all_fds(dont_close, n_dont_close);
}
+static int send_user_lookup(
+ Unit *unit,
+ int user_lookup_fd,
+ uid_t uid,
+ gid_t gid) {
+
+ assert(unit);
+
+ /* Send the resolved UID/GID to PID 1 after we learnt it. We send a single datagram, containing the UID/GID
+ * data as well as the unit name. Note that we suppress sending this if no user/group to resolve was
+ * specified. */
+
+ if (user_lookup_fd < 0)
+ return 0;
+
+ if (!uid_is_valid(uid) && !gid_is_valid(gid))
+ return 0;
+
+ if (writev(user_lookup_fd,
+ (struct iovec[]) {
+ { .iov_base = &uid, .iov_len = sizeof(uid) },
+ { .iov_base = &gid, .iov_len = sizeof(gid) },
+ { .iov_base = unit->id, .iov_len = strlen(unit->id) }}, 3) < 0)
+ return -errno;
+
+ return 0;
+}
+
static int exec_child(
Unit *unit,
ExecCommand *command,
@@ -1769,6 +1801,7 @@ static int exec_child(
int socket_fd,
int *fds, unsigned n_fds,
char **files_env,
+ int user_lookup_fd,
int *exit_status) {
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL;
@@ -1815,7 +1848,7 @@ static int exec_child(
log_forget_fds();
- r = close_remaining_fds(params, runtime, dcreds, socket_fd, fds, n_fds);
+ r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, fds, n_fds);
if (r < 0) {
*exit_status = EXIT_FDS;
return r;
@@ -1902,6 +1935,14 @@ static int exec_child(
}
}
+ r = send_user_lookup(unit, user_lookup_fd, uid, gid);
+ if (r < 0) {
+ *exit_status = EXIT_USER;
+ return r;
+ }
+
+ user_lookup_fd = safe_close(user_lookup_fd);
+
/* If a socket is connected to STDIN/STDOUT/STDERR, we
* must sure to drop O_NONBLOCK */
if (socket_fd >= 0)
@@ -2501,6 +2542,7 @@ int exec_spawn(Unit *unit,
socket_fd,
fds, n_fds,
files_env,
+ unit->manager->user_lookup_fds[1],
&exit_status);
if (r < 0) {
log_open();