diff options
Diffstat (limited to 'src/core/execute.c')
-rw-r--r-- | src/core/execute.c | 46 |
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(); |