diff --git a/0016-KCM-fix-memory-leak.patch b/0016-KCM-fix-memory-leak.patch new file mode 100644 index 0000000..8fe6c23 --- /dev/null +++ b/0016-KCM-fix-memory-leak.patch @@ -0,0 +1,94 @@ +From 58547f020a634cdda4aad0ee350aeb4a894f6669 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Wed, 5 Feb 2025 08:59:49 +0100 +Subject: [PATCH] KCM: fix memory leak +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The copy of 'secret' argument - `secret_val.data` - was left hanging +on `sss_sec_ctx`, effectively resulting in a memory leak. +But this copy isn't actually required as this data isn't modified in +below operations. + +This is a backport of https://github.com/SSSD/sssd/pull/7823 + +:fixes:'sssd_kcm' memory leak was fixed. + +Reviewed-by: Alejandro López +Reviewed-by: Justin Stephenson +(cherry picked from commit 6aba9a7dd2261c19f053d5fbd5358fdaf335b807) +--- + src/responder/kcm/secrets/secrets.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +diff --git a/src/responder/kcm/secrets/secrets.c b/src/responder/kcm/secrets/secrets.c +index a37edcc2a..a0e0154c6 100644 +--- a/src/responder/kcm/secrets/secrets.c ++++ b/src/responder/kcm/secrets/secrets.c +@@ -953,7 +953,7 @@ errno_t sss_sec_put(struct sss_sec_req *req, + size_t secret_len) + { + struct ldb_message *msg; +- struct ldb_val secret_val; ++ const struct ldb_val secret_val = { .length = secret_len, .data = secret }; + int ret; + + if (req == NULL || secret == NULL) { +@@ -1002,13 +1002,11 @@ errno_t sss_sec_put(struct sss_sec_req *req, + goto done; + } + +- secret_val.length = secret_len; +- secret_val.data = talloc_memdup(req->sctx, secret, secret_len); +- if (!secret_val.data) { +- ret = ENOMEM; +- goto done; +- } +- ++ /* `ldb_msg_add_value()` does NOT make a copy of secret_val::*data ++ * but rather copies a pointer under the hood. ++ * This is fine since no operations modifying this data are performed ++ * below and 'msg' is freed before function returns. ++ */ + ret = ldb_msg_add_value(msg, SEC_ATTR_SECRET, &secret_val, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, +@@ -1050,7 +1048,7 @@ errno_t sss_sec_update(struct sss_sec_req *req, + size_t secret_len) + { + struct ldb_message *msg; +- struct ldb_val secret_val; ++ const struct ldb_val secret_val = { .length = secret_len, .data = secret }; + int ret; + + if (req == NULL || secret == NULL) { +@@ -1099,13 +1097,6 @@ errno_t sss_sec_update(struct sss_sec_req *req, + goto done; + } + +- secret_val.length = secret_len; +- secret_val.data = talloc_memdup(req->sctx, secret, secret_len); +- if (!secret_val.data) { +- ret = ENOMEM; +- goto done; +- } +- + /* FIXME - should we have a lastUpdate timestamp? */ + ret = ldb_msg_add_empty(msg, SEC_ATTR_SECRET, LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { +@@ -1115,6 +1106,11 @@ errno_t sss_sec_update(struct sss_sec_req *req, + goto done; + } + ++ /* `ldb_msg_add_value()` does NOT make a copy of secret_val::*data ++ * but rather copies a pointer under the hood. ++ * This is fine since no operations modifying this data are performed ++ * below and 'msg' is freed before function returns. ++ */ + ret = ldb_msg_add_value(msg, SEC_ATTR_SECRET, &secret_val, NULL); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_MINOR_FAILURE, +-- +2.47.0 + diff --git a/0017-KCM-another-memory-leak-fixed.patch b/0017-KCM-another-memory-leak-fixed.patch new file mode 100644 index 0000000..c2aa6fa --- /dev/null +++ b/0017-KCM-another-memory-leak-fixed.patch @@ -0,0 +1,59 @@ +From 85469a77c232f2fe0b95376fe51e3900ab9e9bf0 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Wed, 12 Feb 2025 11:30:22 +0100 +Subject: [PATCH] KCM: another memory leak fixed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +``` +... + talloc_new: src/responder/kcm/kcmsrv_ccache.c:405 contains 0 bytes in 1 blocks (ref 0) 0x563feaabc0a0 + talloc_new: src/responder/kcm/kcmsrv_ccache.c:405 contains 0 bytes in 1 blocks (ref 0) 0x563feaa84f90 + talloc_new: src/responder/kcm/kcmsrv_ccache.c:405 contains 0 bytes in 1 blocks (ref 0) 0x563feaabf520 +... +``` + +Reviewed-by: Alejandro López +(cherry picked from commit 9e72bc242b600158d7920b2b98644efa42fd1ffa) +--- + src/responder/kcm/kcmsrv_ccache.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c +index 6e4ea64e0..4f4f8b46a 100644 +--- a/src/responder/kcm/kcmsrv_ccache.c ++++ b/src/responder/kcm/kcmsrv_ccache.c +@@ -404,7 +404,7 @@ krb5_creds **kcm_cc_unmarshal(TALLOC_CTX *mem_ctx, + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { +- goto done; ++ goto fail; + } + + for (cred = kcm_cc_get_cred(cc); cred != NULL; cred = kcm_cc_next_cred(cred)) { +@@ -417,7 +417,7 @@ krb5_creds **kcm_cc_unmarshal(TALLOC_CTX *mem_ctx, + cred_list[i] = kcm_cred_to_krb5(krb_context, cred); + if (cred_list[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to convert kcm cred to krb5\n"); +- goto done; ++ goto fail; + } + } + +@@ -426,8 +426,10 @@ krb5_creds **kcm_cc_unmarshal(TALLOC_CTX *mem_ctx, + + talloc_steal(mem_ctx, cred_list); + ++ talloc_free(tmp_ctx); + return cred_list; +-done: ++ ++fail: + talloc_free(tmp_ctx); + return NULL; + #endif +-- +2.47.0 + diff --git a/0018-SYSDB-don-t-add-group-members-if-ignore_group_member.patch b/0018-SYSDB-don-t-add-group-members-if-ignore_group_member.patch new file mode 100644 index 0000000..fc7fcfb --- /dev/null +++ b/0018-SYSDB-don-t-add-group-members-if-ignore_group_member.patch @@ -0,0 +1,444 @@ +From ac51851ab114b54d5485af5b20be7fa867c5d541 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Fri, 14 Feb 2025 21:15:16 +0100 +Subject: [PATCH] SYSDB: don't add group members if 'ignore_group_members == + true' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://github.com/SSSD/sssd/issues/7793 + +Reviewed-by: Alejandro López +Reviewed-by: Sumit Bose +(cherry picked from commit 281d9c3ed66ee28a9572433a629eb0d72525ca46) +(cherry picked from commit addb1a78106cab8a85f8f6c56d79e84b5abd0d5e) + +Reviewed-by: Sumit Bose +--- + src/db/sysdb.h | 51 ++++++--- + src/db/sysdb_search.c | 6 +- + src/db/sysdb_views.c | 10 +- + src/tests/cmocka/test_responder_cache_req.c | 112 +++++++------------- + src/tests/cmocka/test_sysdb_ts_cache.c | 6 +- + src/tools/sss_override.c | 2 +- + 6 files changed, 90 insertions(+), 97 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 55c6437f2..fb1ced009 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -276,19 +276,44 @@ + SYSDB_ORIG_DN, \ + NULL} + +-#define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ +- SYSDB_MEMBERUID, \ +- SYSDB_MEMBER, \ +- SYSDB_GHOST, \ +- SYSDB_DEFAULT_ATTRS, \ +- SYSDB_SID_STR, \ +- SYSDB_OVERRIDE_DN, \ +- SYSDB_OVERRIDE_OBJECT_DN, \ +- SYSDB_DEFAULT_OVERRIDE_NAME, \ +- SYSDB_UUID, \ +- ORIGINALAD_PREFIX SYSDB_NAME, \ +- ORIGINALAD_PREFIX SYSDB_GIDNUM, \ +- NULL} ++/* Strictly speaking it should return 'const char * const *' but ++ * that gets really unreadable. ++ */ ++__attribute__((always_inline)) ++static inline const char **SYSDB_GRSRC_ATTRS(const struct sss_domain_info *domain) ++{ ++ static const char * __SYSDB_GRSRC_ATTRS_NO_MEMBERS[] = { ++ SYSDB_NAME, SYSDB_GIDNUM, ++ SYSDB_DEFAULT_ATTRS, ++ SYSDB_SID_STR, ++ SYSDB_OVERRIDE_DN, ++ SYSDB_OVERRIDE_OBJECT_DN, ++ SYSDB_DEFAULT_OVERRIDE_NAME, ++ SYSDB_UUID, ++ NULL ++ }; ++ static const char * __SYSDB_GRSRC_ATTRS_WITH_MEMBERS[] = { ++ SYSDB_NAME, SYSDB_GIDNUM, ++ SYSDB_MEMBERUID, ++ SYSDB_MEMBER, ++ SYSDB_GHOST, ++ SYSDB_DEFAULT_ATTRS, ++ SYSDB_SID_STR, ++ SYSDB_OVERRIDE_DN, ++ SYSDB_OVERRIDE_OBJECT_DN, ++ SYSDB_DEFAULT_OVERRIDE_NAME, ++ SYSDB_UUID, ++ ORIGINALAD_PREFIX SYSDB_NAME, ++ ORIGINALAD_PREFIX SYSDB_GIDNUM, ++ NULL ++ }; ++ ++ if (domain && domain->ignore_group_members) { ++ return __SYSDB_GRSRC_ATTRS_NO_MEMBERS; ++ } else { ++ return __SYSDB_GRSRC_ATTRS_WITH_MEMBERS; ++ } ++} + + #define SYSDB_NETGR_ATTRS {SYSDB_NAME, SYSDB_NETGROUP_TRIPLE, \ + SYSDB_NETGROUP_MEMBER, \ +diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c +index e4c53b853..7f34ddbcb 100644 +--- a/src/db/sysdb_search.c ++++ b/src/db/sysdb_search.c +@@ -1176,7 +1176,7 @@ int sysdb_getgrnam(TALLOC_CTX *mem_ctx, + struct ldb_result **_res) + { + TALLOC_CTX *tmp_ctx; +- static const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + const char *fmt_filter; + char *sanitized_name; + struct ldb_dn *base_dn; +@@ -1378,7 +1378,7 @@ int sysdb_getgrgid_attrs(TALLOC_CTX *mem_ctx, + struct ldb_dn *base_dn; + struct ldb_result *res = NULL; + int ret; +- static const char *default_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **default_attrs = SYSDB_GRSRC_ATTRS(domain); + const char **attrs = NULL; + + tmp_ctx = talloc_new(NULL); +@@ -1484,7 +1484,7 @@ int sysdb_enumgrent_filter(TALLOC_CTX *mem_ctx, + struct ldb_result **_res) + { + TALLOC_CTX *tmp_ctx; +- static const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + const char *filter = NULL; + const char *ts_filter = NULL; + const char *base_filter; +diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c +index 19c10977b..71f627974 100644 +--- a/src/db/sysdb_views.c ++++ b/src/db/sysdb_views.c +@@ -1237,7 +1237,7 @@ errno_t sysdb_search_group_override_by_name(TALLOC_CTX *mem_ctx, + struct ldb_result **override_obj, + struct ldb_result **orig_obj) + { +- const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + + return sysdb_search_override_by_name(mem_ctx, domain, name, + SYSDB_GROUP_NAME_OVERRIDE_FILTER, +@@ -1253,7 +1253,7 @@ static errno_t sysdb_search_override_by_id(TALLOC_CTX *mem_ctx, + { + TALLOC_CTX *tmp_ctx; + static const char *user_attrs[] = SYSDB_PW_ATTRS; +- static const char *group_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **group_attrs = SYSDB_GRSRC_ATTRS(domain); + const char **attrs; + struct ldb_dn *base_dn; + struct ldb_result *override_res; +@@ -1417,7 +1417,7 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain, + struct ldb_message *override; + uint64_t uid; + static const char *user_attrs[] = SYSDB_PW_ATTRS; +- static const char *group_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **group_attrs = SYSDB_GRSRC_ATTRS(domain); /* members don't matter */ + const char **attrs; + struct attr_map { + const char *attr; +@@ -1551,6 +1551,10 @@ errno_t sysdb_add_group_member_overrides(struct sss_domain_info *domain, + char *val; + struct sss_domain_info *orig_dom; + ++ if (domain->ignore_group_members) { ++ return EOK; ++ } ++ + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); +diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c +index fe69a9dfd..c665e1adb 100644 +--- a/src/tests/cmocka/test_responder_cache_req.c ++++ b/src/tests/cmocka/test_responder_cache_req.c +@@ -3282,10 +3282,8 @@ void test_object_by_sid_user_multiple_domains_notfound(void **state) + + void test_object_by_sid_group_cache_valid(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], 1000, time(NULL)); +@@ -3298,10 +3296,8 @@ void test_object_by_sid_group_cache_valid(void **state) + + void test_object_by_sid_group_cache_expired(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], -1000, time(NULL)); +@@ -3320,10 +3316,8 @@ void test_object_by_sid_group_cache_expired(void **state) + + void test_object_by_sid_group_cache_midpoint(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], 50, time(NULL) - 26); +@@ -3341,12 +3335,10 @@ void test_object_by_sid_group_cache_midpoint(void **state) + + void test_object_by_sid_group_ncache(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + errno_t ret; + +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); +- + /* Setup user. */ + ret = sss_ncache_set_sid(test_ctx->ncache, false, test_ctx->tctx->dom, groups[0].sid); + assert_int_equal(ret, EOK); +@@ -3359,10 +3351,8 @@ void test_object_by_sid_group_ncache(void **state) + + void test_object_by_sid_group_missing_found(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return(__wrap_sss_dp_get_account_send, test_ctx); +@@ -3380,10 +3370,8 @@ void test_object_by_sid_group_missing_found(void **state) + + void test_object_by_sid_group_missing_notfound(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return(__wrap_sss_dp_get_account_send, test_ctx); +@@ -3397,17 +3385,13 @@ void test_object_by_sid_group_missing_notfound(void **state) + + void test_object_by_sid_group_multiple_domains_found(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- struct sss_domain_info *domain = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); +- +- /* Setup user. */ +- domain = find_domain_by_name(test_ctx->tctx->dom, +- "responder_cache_req_test_d", true); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct sss_domain_info *domain = find_domain_by_name(test_ctx->tctx->dom, ++ "responder_cache_req_test_d", true); + assert_non_null(domain); ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + ++ /* Setup user. */ + prepare_group(domain, &groups[0], 1000, time(NULL)); + + /* Mock values. */ +@@ -3423,10 +3407,8 @@ void test_object_by_sid_group_multiple_domains_found(void **state) + + void test_object_by_sid_group_multiple_domains_notfound(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return_always(__wrap_sss_dp_get_account_send, test_ctx); +@@ -3605,10 +3587,8 @@ void test_object_by_id_user_multiple_domains_notfound(void **state) + + void test_object_by_id_group_cache_valid(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], 1000, time(NULL)); +@@ -3620,10 +3600,8 @@ void test_object_by_id_group_cache_valid(void **state) + + void test_object_by_id_group_cache_expired(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], -1000, time(NULL)); +@@ -3641,10 +3619,8 @@ void test_object_by_id_group_cache_expired(void **state) + + void test_object_by_id_group_cache_midpoint(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Setup user. */ + prepare_group(test_ctx->tctx->dom, &groups[0], 50, time(NULL) - 26); +@@ -3661,12 +3637,10 @@ void test_object_by_id_group_cache_midpoint(void **state) + + void test_object_by_id_group_ncache(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + errno_t ret; + +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); +- + /* Setup group. We explicitly add the UID into BOTH UID and GID + * namespaces, because otherwise the cache_req plugin would + * search the Data Provider anyway, because it can't be sure +@@ -3693,10 +3667,8 @@ void test_object_by_id_group_ncache(void **state) + + void test_object_by_id_group_missing_found(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return(__wrap_sss_dp_get_account_send, test_ctx); +@@ -3713,10 +3685,8 @@ void test_object_by_id_group_missing_found(void **state) + + void test_object_by_id_group_missing_notfound(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return(__wrap_sss_dp_get_account_send, test_ctx); +@@ -3729,17 +3699,13 @@ void test_object_by_id_group_missing_notfound(void **state) + + void test_object_by_id_group_multiple_domains_found(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- struct sss_domain_info *domain = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); +- +- /* Setup user. */ +- domain = find_domain_by_name(test_ctx->tctx->dom, +- "responder_cache_req_test_d", true); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct sss_domain_info *domain = find_domain_by_name(test_ctx->tctx->dom, ++ "responder_cache_req_test_d", true); + assert_non_null(domain); ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + ++ /* Setup user. */ + prepare_group(domain, &groups[0], 1000, time(NULL)); + + /* Mock values. */ +@@ -3755,10 +3721,8 @@ void test_object_by_id_group_multiple_domains_found(void **state) + + void test_object_by_id_group_multiple_domains_notfound(void **state) + { +- struct cache_req_test_ctx *test_ctx = NULL; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; +- +- test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ struct cache_req_test_ctx *test_ctx = talloc_get_type_abort(*state, struct cache_req_test_ctx); ++ const char **attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + + /* Mock values. */ + will_return_always(__wrap_sss_dp_get_account_send, test_ctx); +diff --git a/src/tests/cmocka/test_sysdb_ts_cache.c b/src/tests/cmocka/test_sysdb_ts_cache.c +index 24b26d950..f349b7061 100644 +--- a/src/tests/cmocka/test_sysdb_ts_cache.c ++++ b/src/tests/cmocka/test_sysdb_ts_cache.c +@@ -694,7 +694,7 @@ static void test_sysdb_getgr_merges(void **state) + struct sysdb_ts_test_ctx *test_ctx = talloc_get_type_abort(*state, + struct sysdb_ts_test_ctx); + struct sysdb_attrs *group_attrs = NULL; +- const char *gr_fetch_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **gr_fetch_attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + char *filter = NULL; + struct ldb_result *res = NULL; + size_t msgs_count; +@@ -783,7 +783,7 @@ static void test_merge_ldb_results(void **state) + int ret; + struct sysdb_ts_test_ctx *test_ctx = talloc_get_type_abort(*state, + struct sysdb_ts_test_ctx); +- const char *gr_fetch_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **gr_fetch_attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + char *filter; + struct ldb_result *res; + struct ldb_result *res1; +@@ -856,7 +856,7 @@ static void test_group_bysid(void **state) + int ret; + struct sysdb_ts_test_ctx *test_ctx = talloc_get_type_abort(*state, + struct sysdb_ts_test_ctx); +- const char *gr_fetch_attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **gr_fetch_attrs = SYSDB_GRSRC_ATTRS(test_ctx->tctx->dom); + struct sysdb_attrs *group_attrs = NULL; + struct ldb_result *res; + struct ldb_message *msg = NULL; +diff --git a/src/tools/sss_override.c b/src/tools/sss_override.c +index cfd8f17fa..a20859c4d 100644 +--- a/src/tools/sss_override.c ++++ b/src/tools/sss_override.c +@@ -1218,7 +1218,7 @@ list_group_overrides(TALLOC_CTX *mem_ctx, + size_t count; + size_t i; + errno_t ret; +- const char *attrs[] = SYSDB_GRSRC_ATTRS; ++ const char **attrs = SYSDB_GRSRC_ATTRS(domain); + const char *fqname; + char *name; + +-- +2.47.0 + diff --git a/0019-SYSDB-Use-SYSDB_NAME-from-cached-entry-when-updating.patch b/0019-SYSDB-Use-SYSDB_NAME-from-cached-entry-when-updating.patch new file mode 100644 index 0000000..6fd7c49 --- /dev/null +++ b/0019-SYSDB-Use-SYSDB_NAME-from-cached-entry-when-updating.patch @@ -0,0 +1,84 @@ +From 402c9a0f8bde56f4d5def3c991c92840a7cc2a86 Mon Sep 17 00:00:00 2001 +From: Samuel Cabrero +Date: Wed, 22 May 2024 13:31:06 +0200 +Subject: [PATCH] SYSDB: Use SYSDB_NAME from cached entry when updating users + and groups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The sysdb_store_user() and sysdb_store_group() functinos search for the +entry by name to check if it is already cached. This search considers +SYSDB_ALIAS, added when the domain is case insensitive. If a matching +entry is found use its SYSDB_NAME instead of the passed name. + +It may happen the group is stored in uppercase, but later some server +returns a memberOf attribute in lowercase. When updating the group to +add the memberships the first search will find the entry, but the modify +operation will fail as the group name in the built DN will differ in case. + +Signed-off-by: Samuel Cabrero + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Pavel Březina +(cherry picked from commit d2b734b926e1f23370c9cabd8ba6f07bf6b29a86) + +Reviewed-by: Justin Stephenson +(cherry picked from commit 4f9fb5fd301d635ad54bf6d0ef93d6811445c7f9) +--- + src/db/sysdb_ops.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index fa2d81217..744e6e879 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -2615,6 +2615,22 @@ int sysdb_store_user(struct sss_domain_info *domain, + } + } else { + /* the user exists, let's just replace attributes when set */ ++ /* ++ * The sysdb_search_user_by_name() function also matches lowercased ++ * aliases, saved when the domain is case-insensitive. This means that ++ * the stored entry name can differ in capitalization from the search ++ * name. Use the cached entry name to perform the modification because ++ * if name capitalization in entry's DN differs the modify operation ++ * will fail. ++ */ ++ const char *entry_name = ++ ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); ++ if (entry_name != NULL) { ++ name = entry_name; ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, "User '%s' without a name?\n", name); ++ } ++ + ret = sysdb_store_user_attrs(domain, name, uid, gid, gecos, homedir, + shell, orig_dn, attrs, remove_attrs, + cache_timeout, now); +@@ -2849,6 +2865,22 @@ int sysdb_store_group(struct sss_domain_info *domain, + ret = sysdb_store_new_group(domain, name, gid, attrs, + cache_timeout, now); + } else { ++ /* ++ * The sysdb_search_group_by_name() function also matches lowercased ++ * aliases, saved when the domain is case-insensitive. This means that ++ * the stored entry name can differ in capitalization from the search ++ * name. Use the cached entry name to perform the modification because ++ * if name capitalization in entry's DN differs the modify operation ++ * will fail. ++ */ ++ const char *entry_name = ++ ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); ++ if (entry_name != NULL) { ++ name = entry_name; ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Group '%s' without a name?\n", name); ++ } ++ + ret = sysdb_store_group_attrs(domain, name, gid, attrs, + cache_timeout, now); + } +-- +2.47.0 + diff --git a/sssd.spec b/sssd.spec index 36d493d..1f8741b 100644 --- a/sssd.spec +++ b/sssd.spec @@ -19,7 +19,7 @@ Name: sssd Version: 2.9.4 -Release: 5%{?dist}.1 +Release: 5%{?dist}.2 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -42,6 +42,10 @@ Patch0012: 0012-sysdb-do-not-fail-to-add-non-posix-user-to-MPG-domai.patch Patch0013: 0013-ldap-add-exop_force-value-for-ldap_pwmodify_mode.patch Patch0014: 0014-DEBUG-reduce-log-level-in-case-a-responder-asks-for-.patch Patch0015: 0015-ldap_child-make-sure-invalid-krb5-context-is-not-use.patch +Patch0016: 0016-KCM-fix-memory-leak.patch +Patch0017: 0017-KCM-another-memory-leak-fixed.patch +Patch0018: 0018-SYSDB-don-t-add-group-members-if-ignore_group_member.patch +Patch0019: 0019-SYSDB-Use-SYSDB_NAME-from-cached-entry-when-updating.patch ### Downstream Patches ### @@ -1226,6 +1230,11 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Fri Apr 25 2025 Alexey Tikhonov - 2.9.4-5.2 +- Resolves: RHEL-78300 - 'sssd_kcm' leaks memory [rhel-8.10.z] +- Resolves: RHEL-82420 - Disk cache failure with large db sizes [rhel-8.10.z] +- Resolves: RHEL-76022 - Use the DN from existing entry when updating a cached group [rhel-8.10.z] + * Fri Nov 22 2024 Alexey Tikhonov - 2.9.4-5.1 - Resolves: RHEL-67671 - Label DP_OPT_DYNDNS_REFRESH_OFFSET has no corresponding option [rhel-8.10.z] - Resolves: RHEL-68507 - sssd backend process segfaults when krb5.conf is invalid [rhel-8.10.z]