From cf8bd44339b00330fdbc91041d6731ba8aba9fec Mon Sep 17 00:00:00 2001 From: Michal Sekletar Date: Thu, 24 Jul 2014 10:40:28 +0200 Subject: socket: introduce SELinuxLabelViaNet option This makes possible to spawn service instances triggered by socket with MLS/MCS SELinux labels which are created based on information provided by connected peer. Implementation of label_get_child_label derived from xinetd. Reviewed-by: Paul Moore --- src/core/execute.c | 23 +++++++++++++++++++++-- src/core/execute.h | 1 + src/core/load-fragment-gperf.gperf.m4 | 3 +++ src/core/socket.c | 22 +++++++++++++++++++--- src/core/socket.h | 2 ++ 5 files changed, 46 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/execute.c b/src/core/execute.c index d8452a666c..129791294e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -83,6 +83,7 @@ #include "af-list.h" #include "mkdir.h" #include "apparmor-util.h" +#include "label.h" #ifdef HAVE_SECCOMP #include "seccomp-util.h" @@ -1729,6 +1730,22 @@ int exec_spawn(ExecCommand *command, goto fail_child; } } + + if (context->selinux_label_via_net && use_selinux()) { + _cleanup_free_ char *label = NULL; + + err = label_get_child_label(socket_fd, command->path, &label); + if (err < 0) { + r = EXIT_SELINUX_CONTEXT; + goto fail_child; + } + + err = setexeccon(label); + if (err < 0) { + r = EXIT_SELINUX_CONTEXT; + goto fail_child; + } + } #endif #ifdef HAVE_APPARMOR @@ -2112,7 +2129,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sPrivateDevices: %s\n" "%sProtectHome: %s\n" "%sProtectSystem: %s\n" - "%sIgnoreSIGPIPE: %s\n", + "%sIgnoreSIGPIPE: %s\n" + "%sSELinuxLabelViaNet: %s\n", prefix, c->umask, prefix, c->working_directory ? c->working_directory : "/", prefix, c->root_directory ? c->root_directory : "/", @@ -2122,7 +2140,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->private_devices), prefix, protect_home_to_string(c->protect_home), prefix, protect_system_to_string(c->protect_system), - prefix, yes_no(c->ignore_sigpipe)); + prefix, yes_no(c->ignore_sigpipe), + prefix, yes_no(c->selinux_label_via_net)); STRV_FOREACH(e, c->environment) fprintf(f, "%sEnvironment: %s\n", prefix, *e); diff --git a/src/core/execute.h b/src/core/execute.h index 9d05d3a9de..d23a98097a 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -136,6 +136,7 @@ struct ExecContext { bool selinux_context_ignore; char *selinux_context; + bool selinux_label_via_net; bool apparmor_profile_ignore; char *apparmor_profile; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b4e2b25743..d5ff848c33 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -262,6 +262,9 @@ Socket.SmackLabelIPOut, config_parse_string, 0, `Socket.SmackLabel, config_parse_warn_compat, 0, 0 Socket.SmackLabelIPIn, config_parse_warn_compat, 0, 0 Socket.SmackLabelIPOut, config_parse_warn_compat, 0, 0') +m4_ifdef(`HAVE_SELINUX', +`Socket.SELinuxLabelViaNet, config_parse_bool, 0, offsetof(Socket, selinux_label_via_net)', +`Socket.SELinuxLabelViaNet, config_parse_warn_compat, 0, 0') EXEC_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl CGROUP_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl KILL_CONTEXT_CONFIG_ITEMS(Socket)m4_dnl diff --git a/src/core/socket.c b/src/core/socket.c index a16b20d739..34ce1b1ffd 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -31,6 +31,10 @@ #include #include +#ifdef HAVE_SELINUX +#include +#endif + #include "sd-event.h" #include "log.h" #include "load-dropin.h" @@ -488,7 +492,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { "%sPassCredentials: %s\n" "%sPassSecurity: %s\n" "%sTCPCongestion: %s\n" - "%sRemoveOnStop: %s\n", + "%sRemoveOnStop: %s\n" + "%sSELinuxLabelViaNet: %s\n", prefix, socket_state_to_string(s->state), prefix, socket_result_to_string(s->result), prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only), @@ -503,7 +508,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->pass_cred), prefix, yes_no(s->pass_sec), prefix, strna(s->tcp_congestion), - prefix, yes_no(s->remove_on_stop)); + prefix, yes_no(s->remove_on_stop), + prefix, yes_no(s->selinux_label_via_net)); if (s->control_pid > 0) fprintf(f, @@ -1130,7 +1136,14 @@ static int socket_open_fds(Socket *s) { continue; if (p->type == SOCKET_SOCKET) { - +#ifdef HAVE_SELINUX + if (!know_label && s->selinux_label_via_net) { + r = getcon(&label); + if (r < 0) + return r; + know_label = true; + } +#endif if (!know_label) { r = socket_instantiate_service(s); @@ -1829,6 +1842,9 @@ static void socket_enter_running(Socket *s, int cfd) { cfd = -1; s->n_connections ++; + if (s->selinux_label_via_net) + service->exec_context.selinux_label_via_net = true; + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL); if (r < 0) goto fail; diff --git a/src/core/socket.h b/src/core/socket.h index eede70564a..ab342c34e8 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -165,6 +165,8 @@ struct Socket { char *smack_ip_in; char *smack_ip_out; + bool selinux_label_via_net; + char *user, *group; }; -- cgit v1.2.3-54-g00ecf