diff options
author | Daniel Mack <zonque@gmail.com> | 2014-08-22 19:02:03 +0200 |
---|---|---|
committer | Daniel Mack <daniel@zonque.org> | 2014-09-08 14:15:02 +0200 |
commit | e44da745d19b9e02e67e32ea82c3bad86175120c (patch) | |
tree | 7b7192f12d3607faea9c985020eb85fb569b1c28 /src/core/service.c | |
parent | 060e088e94852cbe166592429c330e3997c21c4c (diff) |
service: hook up custom endpoint logic
If BusPolicy= was passed, the parser function will have created
an ExecContext->bus_endpoint object, along with policy information.
In that case, create a kdbus endpoint, and pass its path name to the
namespace logic, to it will be mounted over the actual 'bus' node.
At endpoint creation time, no policy is updloaded. That is done after
fork(), through a separate call. This is necessary because we don't
know the real uid of the process earlier than that.
Diffstat (limited to 'src/core/service.c')
-rw-r--r-- | src/core/service.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/src/core/service.c b/src/core/service.c index f3775f24c4..3f6595c5c8 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -45,6 +45,7 @@ #include "fileio.h" #include "bus-error.h" #include "bus-util.h" +#include "bus-kernel.h" static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { [SERVICE_DEAD] = UNIT_INACTIVE, @@ -102,6 +103,7 @@ static void service_init(Unit *u) { s->restart_usec = u->manager->default_restart_usec; s->type = _SERVICE_TYPE_INVALID; s->socket_fd = -1; + s->bus_endpoint_fd = -1; s->guess_main_pid = true; RATELIMIT_INIT(s->start_limit, u->manager->default_start_limit_interval, u->manager->default_start_limit_burst); @@ -273,6 +275,7 @@ static void service_done(Unit *u) { s->bus_name = NULL; } + s->bus_endpoint_fd = safe_close(s->bus_endpoint_fd); service_close_socket_fd(s); service_connection_unref(s); @@ -889,6 +892,7 @@ static int service_spawn( int *fds = NULL; _cleanup_free_ int *fdsbuf = NULL; unsigned n_fds = 0, n_env = 0; + _cleanup_free_ char *bus_endpoint_path = NULL; _cleanup_strv_free_ char **argv = NULL, **final_env = NULL, **our_env = NULL; const char *path; @@ -896,6 +900,7 @@ static int service_spawn( .apply_permissions = apply_permissions, .apply_chroot = apply_chroot, .apply_tty_stdin = apply_tty_stdin, + .bus_endpoint_fd = -1, }; assert(s); @@ -972,6 +977,20 @@ static int service_spawn( } else path = UNIT(s)->cgroup_path; +#ifdef ENABLE_KDBUS + if (s->exec_context.bus_endpoint) { + r = bus_kernel_create_endpoint(UNIT(s)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user", + UNIT(s)->id, &bus_endpoint_path); + if (r < 0) + goto fail; + + /* Pass the fd to the exec_params so that the child process can upload the policy. + * Keep a reference to the fd in the service, so the endpoint is kept alive as long + * as the service is running. */ + exec_params.bus_endpoint_fd = s->bus_endpoint_fd = r; + } +#endif + exec_params.argv = argv; exec_params.fds = fds; exec_params.n_fds = n_fds; @@ -982,6 +1001,7 @@ static int service_spawn( exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager); exec_params.unit_id = UNIT(s)->id; exec_params.watchdog_usec = s->watchdog_usec; + exec_params.bus_endpoint_path = bus_endpoint_path; if (s->type == SERVICE_IDLE) exec_params.idle_pipe = UNIT(s)->manager->idle_pipe; @@ -1770,6 +1790,15 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { unit_serialize_item_format(u, f, "socket-fd", "%i", copy); } + if (s->bus_endpoint_fd >= 0) { + int copy; + + if ((copy = fdset_put_dup(fds, s->bus_endpoint_fd)) < 0) + return copy; + + unit_serialize_item_format(u, f, "endpoint-fd", "%i", copy); + } + if (s->main_exec_status.pid > 0) { unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid); @@ -1879,10 +1908,18 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) log_debug_unit(u->id, "Failed to parse socket-fd value %s", value); else { - asynchronous_close(s->socket_fd); s->socket_fd = fdset_remove(fds, fd); } + } else if (streq(key, "endpoint-fd")) { + int fd; + + if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) + log_debug_unit(u->id, "Failed to parse endpoint-fd value %s", value); + else { + safe_close(s->bus_endpoint_fd); + s->bus_endpoint_fd = fdset_remove(fds, fd); + } } else if (streq(key, "main-exec-status-pid")) { pid_t pid; |