Fix slow login with ipa and SELinux

- Resolves: upstream #2624 - Only set the selinux context if the context
                             differs from the local one
This commit is contained in:
Lukas Slebodnik 2015-04-15 14:17:32 +02:00
parent 9a0389188d
commit c4cf951d60
4 changed files with 351 additions and 0 deletions

View File

@ -0,0 +1,69 @@
From 8f4a60a1fb0c24cfb01bc683a31b52786df68ccc Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Fri, 10 Apr 2015 10:55:22 +0200
Subject: [PATCH 18/20] selinux: Disconnect before closing the handle
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
libsemanage documentation says:
~~~~
be sure that a semanage_disconnect() was previously called if the handle
was connected.
~~~~
Otherwise we get a memory leak.
Reviewed-by: Michal Židek <mzidek@redhat.com>
---
src/util/sss_semanage.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
index b85831c3d3f262f49b19082e96aa62ccf3afeaa8..d141de1c671e6d62a731e56b10ee14069f27ae87 100644
--- a/src/util/sss_semanage.c
+++ b/src/util/sss_semanage.c
@@ -68,6 +68,13 @@ static void sss_semanage_error_callback(void *varg,
free(message);
}
+static void sss_semanage_close(semanage_handle_t *handle)
+{
+ /* Calling disconnect on a disconnected handle is safe */
+ semanage_disconnect(handle);
+ semanage_handle_destroy(handle);
+}
+
static semanage_handle_t *sss_semanage_init(void)
{
int ret;
@@ -110,7 +117,7 @@ static semanage_handle_t *sss_semanage_init(void)
return handle;
fail:
- semanage_handle_destroy(handle);
+ sss_semanage_close(handle);
return NULL;
}
@@ -278,7 +285,7 @@ int set_seuser(const char *login_name, const char *seuser_name,
ret = EOK;
done:
semanage_seuser_key_free(key);
- semanage_handle_destroy(handle);
+ sss_semanage_close(handle);
return ret;
}
@@ -350,7 +357,7 @@ int del_seuser(const char *login_name)
ret = EOK;
done:
- semanage_handle_destroy(handle);
+ sss_semanage_close(handle);
return ret;
}
--
2.3.5

View File

@ -0,0 +1,67 @@
From 342165ced656d64ec78bdb6f8897e15666cc08d2 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Fri, 10 Apr 2015 11:06:44 +0200
Subject: [PATCH 19/20] selinux: Begin and end the transaction on the same
nesting level
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Transaction should be started and commited on the same code nesting or
abstraction level. Also, transactions are really costly with libselinux
and splitting them from initialization will make init function reusable
by read-only libsemanage functions.
Reviewed-by: Michal Židek <mzidek@redhat.com>
---
src/util/sss_semanage.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
index d141de1c671e6d62a731e56b10ee14069f27ae87..c0342498cbd0495733a0bf701a06a02cfb705fc7 100644
--- a/src/util/sss_semanage.c
+++ b/src/util/sss_semanage.c
@@ -109,12 +109,6 @@ static semanage_handle_t *sss_semanage_init(void)
goto fail;
}
- ret = semanage_begin_transaction(handle);
- if (ret != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot begin SELinux transaction\n");
- goto fail;
- }
-
return handle;
fail:
sss_semanage_close(handle);
@@ -243,6 +237,13 @@ int set_seuser(const char *login_name, const char *seuser_name,
goto done;
}
+ ret = semanage_begin_transaction(handle);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot begin SELinux transaction\n");
+ ret = EIO;
+ goto done;
+ }
+
ret = semanage_seuser_key_create(handle, login_name, &key);
if (ret != 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux user key\n");
@@ -303,6 +304,13 @@ int del_seuser(const char *login_name)
goto done;
}
+ ret = semanage_begin_transaction(handle);
+ if (ret != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot begin SELinux transaction\n");
+ ret = EIO;
+ goto done;
+ }
+
ret = semanage_seuser_key_create(handle, login_name, &key);
if (ret != 0) {
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux user key\n");
--
2.3.5

View File

@ -0,0 +1,207 @@
From 92a0931dfc57ec386b4c797ff4a144d2de7ffc25 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Thu, 9 Apr 2015 22:18:35 +0200
Subject: [PATCH 20/20] selinux: Only call semanage if the context actually
changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://fedorahosted.org/sssd/ticket/2624
Add a function to query the libsemanage database for a user context and
only update the database if the context differes from the one set on the
server.
Adds talloc dependency to libsss_semanage.
Reviewed-by: Michal Židek <mzidek@redhat.com>
---
Makefile.am | 5 +++
src/providers/ipa/selinux_child.c | 35 ++++++++++++++++---
src/util/sss_semanage.c | 71 +++++++++++++++++++++++++++++++++++++++
src/util/util.h | 2 ++
4 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 605fd1ff5e479078d579ac7524507546261d469c..ed89028ebdbb85752f1f7f06ef8464613ee96377 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -784,10 +784,15 @@ endif
libsss_util_la_LDFLAGS = -avoid-version
pkglib_LTLIBRARIES += libsss_semanage.la
+libsss_semanage_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(TALLOC_CFLAGS) \
+ $(NULL)
libsss_semanage_la_SOURCES = \
src/util/sss_semanage.c \
$(NULL)
libsss_semanage_la_LIBADD = \
+ $(TALLOC_LIBS) \
libsss_debug.la \
$(NULL)
if BUILD_SEMANAGE
diff --git a/src/providers/ipa/selinux_child.c b/src/providers/ipa/selinux_child.c
index 81c1de877ef08a299d07837fefcd195d465849fa..7c5731d66b7d0ed17b7be18c4adaa65394002fc4 100644
--- a/src/providers/ipa/selinux_child.c
+++ b/src/providers/ipa/selinux_child.c
@@ -165,6 +165,29 @@ static int sc_set_seuser(const char *login_name, const char *seuser_name,
return ret;
}
+static bool seuser_needs_update(struct input_buffer *ibuf)
+{
+ bool needs_update = true;
+ char *db_seuser = NULL;
+ char *db_mls_range = NULL;
+ errno_t ret;
+
+ ret = get_seuser(ibuf, ibuf->username, &db_seuser, &db_mls_range);
+ DEBUG(SSSDBG_TRACE_INTERNAL,
+ "get_seuser: ret: %d seuser: %s mls: %s\n",
+ ret, db_seuser ? db_seuser : "unknown",
+ db_mls_range ? db_mls_range : "unknown");
+ if (ret == EOK && db_seuser && db_mls_range &&
+ strcmp(db_seuser, ibuf->seuser) == 0 &&
+ strcmp(db_mls_range, ibuf->mls_range) == 0) {
+ needs_update = false;
+ }
+
+ talloc_free(db_seuser);
+ talloc_free(db_mls_range);
+ return needs_update;
+}
+
int main(int argc, const char *argv[])
{
int opt;
@@ -177,6 +200,7 @@ int main(int argc, const char *argv[])
struct input_buffer *ibuf = NULL;
struct response *resp = NULL;
ssize_t written;
+ bool needs_update;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -296,10 +320,13 @@ int main(int argc, const char *argv[])
DEBUG(SSSDBG_TRACE_FUNC, "performing selinux operations\n");
- ret = sc_set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
- goto fail;
+ needs_update = seuser_needs_update(ibuf);
+ if (needs_update == true) {
+ ret = sc_set_seuser(ibuf->username, ibuf->seuser, ibuf->mls_range);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set SELinux login context.\n");
+ goto fail;
+ }
}
ret = prepare_response(main_ctx, ret, &resp);
diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c
index c0342498cbd0495733a0bf701a06a02cfb705fc7..01a2f41d8752e127f2aa1b72faa61c23f315edd7 100644
--- a/src/util/sss_semanage.c
+++ b/src/util/sss_semanage.c
@@ -369,6 +369,71 @@ done:
return ret;
}
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range)
+{
+ errno_t ret;
+ const char *seuser;
+ const char *mls_range;
+ semanage_handle_t *sm_handle = NULL;
+ semanage_seuser_t *sm_user = NULL;
+ semanage_seuser_key_t *sm_key = NULL;
+
+ sm_handle = sss_semanage_init();
+ if (sm_handle == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create SELinux handle\n");
+ ret = EIO;
+ goto done;
+ }
+
+ ret = semanage_seuser_key_create(sm_handle, login_name, &sm_key);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create key for %s\n", login_name);
+ ret = EIO;
+ goto done;
+ }
+
+ ret = semanage_seuser_query(sm_handle, sm_key, &sm_user);
+ if (ret < 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot query for %s\n", login_name);
+ ret = EIO;
+ goto done;
+ }
+
+ seuser = semanage_seuser_get_sename(sm_user);
+ if (seuser != NULL) {
+ *_seuser = talloc_strdup(mem_ctx, seuser);
+ if (*_seuser == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_OP_FAILURE,
+ "SELinux user for %s: %s\n", login_name, *_seuser);
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get sename for %s\n", login_name);
+ }
+
+ mls_range = semanage_seuser_get_mlsrange(sm_user);
+ if (mls_range != NULL) {
+ *_mls_range = talloc_strdup(mem_ctx, mls_range);
+ if (*_mls_range == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(SSSDBG_OP_FAILURE,
+ "SELinux range for %s: %s\n", login_name, *_mls_range);
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get mlsrange for %s\n", login_name);
+ }
+
+ ret = EOK;
+done:
+ semanage_seuser_key_free(sm_key);
+ semanage_seuser_free(sm_user);
+ sss_semanage_close(sm_handle);
+ return ret;
+}
+
#else /* HAVE_SEMANAGE */
int set_seuser(const char *login_name, const char *seuser_name,
const char *mls)
@@ -380,4 +445,10 @@ int del_seuser(const char *login_name)
{
return EOK;
}
+
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range)
+{
+ return EOK;
+}
#endif /* HAVE_SEMANAGE */
diff --git a/src/util/util.h b/src/util/util.h
index bf3a9a057aed77e93949370f8651af2631d91432..d217688f81d7a2e49cd3eaaf0d1be609a0f679ea 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -635,5 +635,7 @@ errno_t restore_creds(struct sss_creds *saved_creds);
int set_seuser(const char *login_name, const char *seuser_name,
const char *mlsrange);
int del_seuser(const char *login_name);
+int get_seuser(TALLOC_CTX *mem_ctx, const char *login_name,
+ char **_seuser, char **_mls_range);
#endif /* __SSSD_UTIL_H__ */
--
2.3.5

View File

@ -53,6 +53,9 @@ Patch0014: 0014-SPEC-Replace-python_-macros-with-python2_.patch
Patch0015: 0015-SPEC-Build-python3-bindings-on-available-platforms.patch
Patch0016: 0016-selinux-Delete-existing-user-mapping-on-empty-defaul.patch
Patch0017: 0017-selinux-Handle-setup-with-empty-default-and-no-confi.patch
Patch0018: 0018-selinux-Disconnect-before-closing-the-handle.patch
Patch0019: 0019-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch
Patch0020: 0020-selinux-Only-call-semanage-if-the-context-actually-c.patch
### Dependencies ###
Requires: sssd-common = %{version}-%{release}
@ -1012,6 +1015,11 @@ if [ $1 -eq 0 ]; then
fi
%changelog
* Wed Apr 15 2015 Lukas Slebodnik <lslebodn@redhat.com> - 1.12.4-6
- Fix slow login with ipa and SELinux
- Resolves: upstream #2624 - Only set the selinux context if the context
differs from the local one
* Mon Mar 23 2015 Lukas Slebodnik <lslebodn@redhat.com> - 1.12.4-5
- Fix regressions with ipa and SELinux
- Resolves: upstream #2587 - With empty ipaselinuxusermapdefault security