summaryrefslogtreecommitdiff
path: root/src/core/service.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-08-22 19:02:03 +0200
committerDaniel Mack <daniel@zonque.org>2014-09-08 14:15:02 +0200
commite44da745d19b9e02e67e32ea82c3bad86175120c (patch)
tree7b7192f12d3607faea9c985020eb85fb569b1c28 /src/core/service.c
parent060e088e94852cbe166592429c330e3997c21c4c (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.c39
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;