diff --git a/0003-selinux-Disconnect-before-closing-the-handle.patch b/0003-selinux-Disconnect-before-closing-the-handle.patch new file mode 100644 index 0000000..7b16e35 --- /dev/null +++ b/0003-selinux-Disconnect-before-closing-the-handle.patch @@ -0,0 +1,70 @@ +From 24553c550248ac1a989f43921d2a3b45295b42cd Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 10 Apr 2015 10:55:22 +0200 +Subject: [PATCH 3/5] 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 +(cherry picked from commit aa00d67b2a8e07c9080e7798defdc6c774c93465) +--- + 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/0004-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch b/0004-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch new file mode 100644 index 0000000..ee7e132 --- /dev/null +++ b/0004-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch @@ -0,0 +1,68 @@ +From 47987b0af3b1898a0ed5a772dbc4438b59fba8c8 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 10 Apr 2015 11:06:44 +0200 +Subject: [PATCH 4/5] 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 +(cherry picked from commit 748b38a7991d78cbf4726f2a14ace5e926629a54) +--- + 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/0005-selinux-Only-call-semanage-if-the-context-actually-c.patch b/0005-selinux-Only-call-semanage-if-the-context-actually-c.patch new file mode 100644 index 0000000..ee1b9ca --- /dev/null +++ b/0005-selinux-Only-call-semanage-if-the-context-actually-c.patch @@ -0,0 +1,208 @@ +From 566c45a78757c73700ce9535d70fa37c8077e678 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Thu, 9 Apr 2015 22:18:35 +0200 +Subject: [PATCH 5/5] 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 +(cherry picked from commit 1e0fa55fb377db788e065de917ba8e149eb56161) +--- + 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 29d148c4a0cbda6882b4a619d6c71d2efcc8fb43..73970024a6ce55bfe91c5e14d5127d189e321716 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -767,10 +767,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 841c392..3fbf5ec 100644 --- a/sssd.spec +++ b/sssd.spec @@ -27,7 +27,7 @@ Name: sssd Version: 1.12.4 -Release: 2%{?dist} +Release: 3%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -38,6 +38,9 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) ### Patches ### Patch0001: 0001-selinux-Delete-existing-user-mapping-on-empty-defaul.patch Patch0002: 0002-selinux-Handle-setup-with-empty-default-and-no-confi.patch +Patch0003: 0003-selinux-Disconnect-before-closing-the-handle.patch +Patch0004: 0004-selinux-Begin-and-end-the-transaction-on-the-same-ne.patch +Patch0005: 0005-selinux-Only-call-semanage-if-the-context-actually-c.patch ### Dependencies ### Requires: sssd-common = %{version}-%{release} @@ -904,6 +907,11 @@ if [ $1 -eq 0 ]; then fi %changelog +* Wed Apr 15 2015 Lukas Slebodnik - 1.12.4-3 +- 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-2 - Fix regressions with ipa and SELinux - Resolves: upstream #2587 - With empty ipaselinuxusermapdefault security