diff --git a/0018-selinux-Disconnect-before-closing-the-handle.patch b/0018-selinux-Disconnect-before-closing-the-handle.patch new file mode 100644 index 0000000..7407760 --- /dev/null +++ b/0018-selinux-Disconnect-before-closing-the-handle.patch @@ -0,0 +1,69 @@ +From 8f4a60a1fb0c24cfb01bc683a31b52786df68ccc Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +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 +--- + 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 + diff --git a/0019-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch b/0019-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch new file mode 100644 index 0000000..828c740 --- /dev/null +++ b/0019-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch @@ -0,0 +1,67 @@ +From 342165ced656d64ec78bdb6f8897e15666cc08d2 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +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 +--- + 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 + diff --git a/0020-selinux-Only-call-semanage-if-the-context-actually-c.patch b/0020-selinux-Only-call-semanage-if-the-context-actually-c.patch new file mode 100644 index 0000000..7ec762b --- /dev/null +++ b/0020-selinux-Only-call-semanage-if-the-context-actually-c.patch @@ -0,0 +1,207 @@ +From 92a0931dfc57ec386b4c797ff4a144d2de7ffc25 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +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 +--- + 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 + diff --git a/sssd.spec b/sssd.spec index 62dc11d..3a855ca 100644 --- a/sssd.spec +++ b/sssd.spec @@ -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 - 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 - 1.12.4-5 - Fix regressions with ipa and SELinux - Resolves: upstream #2587 - With empty ipaselinuxusermapdefault security