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]
This commit is contained in:
Alexey Tikhonov 2025-04-25 19:21:51 +02:00
parent e0d298f0ae
commit f325649f9d
5 changed files with 691 additions and 1 deletions

View File

@ -0,0 +1,94 @@
From 58547f020a634cdda4aad0ee350aeb4a894f6669 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
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 <allopez@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(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

View File

@ -0,0 +1,59 @@
From 85469a77c232f2fe0b95376fe51e3900ab9e9bf0 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
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 <allopez@redhat.com>
(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

View File

@ -0,0 +1,444 @@
From ac51851ab114b54d5485af5b20be7fa867c5d541 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
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 <allopez@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
(cherry picked from commit 281d9c3ed66ee28a9572433a629eb0d72525ca46)
(cherry picked from commit addb1a78106cab8a85f8f6c56d79e84b5abd0d5e)
Reviewed-by: Sumit Bose <sbose@redhat.com>
---
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

View File

@ -0,0 +1,84 @@
From 402c9a0f8bde56f4d5def3c991c92840a7cc2a86 Mon Sep 17 00:00:00 2001
From: Samuel Cabrero <scabrero@suse.de>
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 <scabrero@suse.de>
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
(cherry picked from commit d2b734b926e1f23370c9cabd8ba6f07bf6b29a86)
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
(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

View File

@ -19,7 +19,7 @@
Name: sssd Name: sssd
Version: 2.9.4 Version: 2.9.4
Release: 5%{?dist}.1 Release: 5%{?dist}.2
Group: Applications/System Group: Applications/System
Summary: System Security Services Daemon Summary: System Security Services Daemon
License: GPLv3+ 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 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 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 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 ### ### Downstream Patches ###
@ -1226,6 +1230,11 @@ fi
%systemd_postun_with_restart sssd.service %systemd_postun_with_restart sssd.service
%changelog %changelog
* Fri Apr 25 2025 Alexey Tikhonov <atikhono@redhat.com> - 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 <atikhono@redhat.com> - 2.9.4-5.1 * Fri Nov 22 2024 Alexey Tikhonov <atikhono@redhat.com> - 2.9.4-5.1
- Resolves: RHEL-67671 - Label DP_OPT_DYNDNS_REFRESH_OFFSET has no corresponding option [rhel-8.10.z] - 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] - Resolves: RHEL-68507 - sssd backend process segfaults when krb5.conf is invalid [rhel-8.10.z]