Blame SOURCES/0106-nss-add-a-netgroup-counter-to-struct-nss_enum_index.patch

ab1ddb
From f9859498b52d89bf60dbddd898752f859f4952d3 Mon Sep 17 00:00:00 2001
ab1ddb
From: Sumit Bose <sbose@redhat.com>
ab1ddb
Date: Thu, 15 Mar 2018 12:50:20 +0100
ab1ddb
Subject: [PATCH] nss: add a netgroup counter to struct nss_enum_index
ab1ddb
ab1ddb
Netgroups are not looked up with the help of a single request but by
ab1ddb
calling setnetgrent(), getnetgrent() and endnetgrent() where
ab1ddb
getnetgrent() might be called multiple times depending on the number of
ab1ddb
netgroup elements. Since the caller does not provide a state the state
ab1ddb
has to be maintained by the SSSD nss responder. Besides the netgroup
ab1ddb
name this is mainly the number of elements already returned.
ab1ddb
ab1ddb
This number is used to select the next element to return and currently
ab1ddb
it is assumed that there are not changes to the netgroup while the
ab1ddb
client is requesting the individual elements. But if e.g. the 3 nss
ab1ddb
calls are not used correctly or the netgroup is modified while the
ab1ddb
client is sending getnetgrent() calls the stored number might be out of
ab1ddb
range. To be on the safe side the stored number should be always
ab1ddb
compared with the current number of netgroup elements.
ab1ddb
ab1ddb
Related to https://pagure.io/SSSD/sssd/issue/3679
ab1ddb
ab1ddb
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
ab1ddb
(cherry picked from commit 08db22b1b1a2e742edbca92e35087294d963adda)
ab1ddb
ab1ddb
DOWNSTREAM:
ab1ddb
Resolves: rhbz#1579703 - crash in nss_protocol_fill_netgrent. sssd_nss[19234]: segfault at 80 ip 000055612688c2a0 sp 00007ffddf9b9cd0 error 4 in sssd_nss[55612687e000+39000] [rhel-7.5.z]
ab1ddb
---
ab1ddb
 src/db/sysdb.h                         | 3 ++-
ab1ddb
 src/db/sysdb_search.c                  | 5 ++++-
ab1ddb
 src/responder/nss/nss_enum.c           | 3 ++-
ab1ddb
 src/responder/nss/nss_private.h        | 1 +
ab1ddb
 src/responder/nss/nss_protocol_netgr.c | 7 +++++++
ab1ddb
 5 files changed, 16 insertions(+), 3 deletions(-)
ab1ddb
ab1ddb
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
ab1ddb
index fd18ecefed2b2c5f35060fa47fd160a8968e073b..2660314a75a574d7f5625c8672e5261587056d1a 100644
ab1ddb
--- a/src/db/sysdb.h
ab1ddb
+++ b/src/db/sysdb.h
ab1ddb
@@ -1219,7 +1219,8 @@ errno_t sysdb_attrs_to_list(TALLOC_CTX *mem_ctx,
ab1ddb
 
ab1ddb
 errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx,
ab1ddb
                                struct ldb_result *res,
ab1ddb
-                               struct sysdb_netgroup_ctx ***entries);
ab1ddb
+                               struct sysdb_netgroup_ctx ***entries,
ab1ddb
+                               size_t *netgroup_count);
ab1ddb
 
ab1ddb
 errno_t sysdb_dn_sanitize(TALLOC_CTX *mem_ctx, const char *input,
ab1ddb
                           char **sanitized);
ab1ddb
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
ab1ddb
index a6a81e23d257331614085403b4dca8ded860600b..9f37cbcd50a778145518c15b6146ad812a5b4fa3 100644
ab1ddb
--- a/src/db/sysdb_search.c
ab1ddb
+++ b/src/db/sysdb_search.c
ab1ddb
@@ -1829,7 +1829,8 @@ done:
ab1ddb
 
ab1ddb
 errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx,
ab1ddb
                                struct ldb_result *res,
ab1ddb
-                               struct sysdb_netgroup_ctx ***entries)
ab1ddb
+                               struct sysdb_netgroup_ctx ***entries,
ab1ddb
+                               size_t *netgroup_count)
ab1ddb
 {
ab1ddb
     errno_t ret;
ab1ddb
     size_t size = 0;
ab1ddb
@@ -1933,6 +1934,8 @@ errno_t sysdb_netgr_to_entries(TALLOC_CTX *mem_ctx,
ab1ddb
     tmp_entry[c] = NULL;
ab1ddb
 
ab1ddb
     *entries = talloc_steal(mem_ctx, tmp_entry);
ab1ddb
+    *netgroup_count = c;
ab1ddb
+
ab1ddb
     ret = EOK;
ab1ddb
 
ab1ddb
 done:
ab1ddb
diff --git a/src/responder/nss/nss_enum.c b/src/responder/nss/nss_enum.c
ab1ddb
index da844fbced529f606a3e98669fb7b95e0696ce00..b2b22bbae8a373ed3abb47381fabd989d4931690 100644
ab1ddb
--- a/src/responder/nss/nss_enum.c
ab1ddb
+++ b/src/responder/nss/nss_enum.c
ab1ddb
@@ -144,7 +144,8 @@ static void nss_setent_internal_done(struct tevent_req *subreq)
ab1ddb
             /* We need to expand the netgroup into triples and members. */
ab1ddb
             ret = sysdb_netgr_to_entries(state->enum_ctx,
ab1ddb
                                          result[0]->ldb_result,
ab1ddb
-                                         &state->enum_ctx->netgroup);
ab1ddb
+                                         &state->enum_ctx->netgroup,
ab1ddb
+                                         &state->enum_ctx->netgroup_count);
ab1ddb
             if (ret != EOK) {
ab1ddb
                 goto done;
ab1ddb
             }
ab1ddb
diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h
ab1ddb
index 5fc19d26be9adda4d967086e7b239e49a78866ee..aa8d8e9cde0d73e72d3aa4c186f104d6baae411f 100644
ab1ddb
--- a/src/responder/nss/nss_private.h
ab1ddb
+++ b/src/responder/nss/nss_private.h
ab1ddb
@@ -41,6 +41,7 @@ struct nss_enum_index {
ab1ddb
 struct nss_enum_ctx {
ab1ddb
     struct cache_req_result **result;
ab1ddb
     struct sysdb_netgroup_ctx **netgroup;
ab1ddb
+    size_t netgroup_count;
ab1ddb
 
ab1ddb
     /* Ongoing cache request that is constructing enumeration result. */
ab1ddb
     struct tevent_req *ongoing;
ab1ddb
diff --git a/src/responder/nss/nss_protocol_netgr.c b/src/responder/nss/nss_protocol_netgr.c
ab1ddb
index ed04fd25821031554e20e14afebaca9b828a748b..9f27c6b78d47f188dea99600a634a18be2512bfb 100644
ab1ddb
--- a/src/responder/nss/nss_protocol_netgr.c
ab1ddb
+++ b/src/responder/nss/nss_protocol_netgr.c
ab1ddb
@@ -126,6 +126,13 @@ nss_protocol_fill_netgrent(struct nss_ctx *nss_ctx,
ab1ddb
     idx = cmd_ctx->enum_index;
ab1ddb
     entries = cmd_ctx->enum_ctx->netgroup;
ab1ddb
 
ab1ddb
+    if (idx->result > cmd_ctx->enum_ctx->netgroup_count) {
ab1ddb
+        DEBUG(SSSDBG_CRIT_FAILURE,
ab1ddb
+              "Unconsistent state while processing netgroups.\n");
ab1ddb
+        ret = EINVAL;
ab1ddb
+        goto done;
ab1ddb
+    }
ab1ddb
+
ab1ddb
     /* First two fields (length and reserved), filled up later. */
ab1ddb
     ret = sss_packet_grow(packet, 2 * sizeof(uint32_t));
ab1ddb
     if (ret != EOK) {
ab1ddb
-- 
ab1ddb
2.17.0
ab1ddb