From 1e0fa55fb377db788e065de917ba8e149eb56161 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Thu, 9 Apr 2015 22:18:35 +0200 Subject: 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 d9724093d..52fbd510d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -789,10 +789,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 81c1de877..7c5731d66 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 c0342498c..01a2f41d8 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 d831d533f..c86bcea5b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -655,6 +655,8 @@ 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); /* convert time from generalized form to unix time */ errno_t sss_utc_to_time_t(const char *str, const char *format, time_t *unix_time); -- cgit