[SSSD] [PATCHES] The fast memory cache should cache initgroups

Lukas Slebodnik lslebodn at redhat.com
Tue Jun 30 22:08:42 UTC 2015


On (30/06/15 23:10), Lukas Slebodnik wrote:
>ehlo,
>
>patches are attached.
>
There was a missing break cuased by wrong rebase.

LS
-------------- next part --------------
>From 6cd4f20386a6f831f07753650b09ca0358c15bb6 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Sat, 23 May 2015 17:02:30 +0200
Subject: [PATCH 1/8] mmap_cache: remove dead increment

---
 src/responder/nss/nsssrv_mmap_cache.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 2d159eb11add2014612c21d2061942cb1afa553c..18f83e1666953d146a80d2dee48d65e0ca41ed6a 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -740,7 +740,6 @@ errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx **_mcc,
     memcpy(&data->strs[pos], homedir->str, homedir->len);
     pos += homedir->len;
     memcpy(&data->strs[pos], shell->str, shell->len);
-    pos += shell->len;
 
     MC_LOWER_BARRIER(rec);
 
@@ -879,7 +878,6 @@ int sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
     memcpy(&data->strs[pos], pw->str, pw->len);
     pos += pw->len;
     memcpy(&data->strs[pos], membuf, memsize);
-    pos += memsize;
 
     MC_LOWER_BARRIER(rec);
 
-- 
2.4.3

-------------- next part --------------
>From 2d4c4b710063019b2796f50b38e725e11e693a2f Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 30 Jun 2015 13:50:51 +0200
Subject: [PATCH 2/8] nss: Store entries in responder to initgr mmap cache

Resolves:
https://fedorahosted.org/sssd/ticket/2485
---
 src/responder/nss/nsssrv.c            | 16 +++++++++
 src/responder/nss/nsssrv.h            |  1 +
 src/responder/nss/nsssrv_cmd.c        | 30 +++++++++++++---
 src/responder/nss/nsssrv_mmap_cache.c | 64 +++++++++++++++++++++++++++++++++++
 src/responder/nss/nsssrv_mmap_cache.h |  9 +++++
 src/util/mmap_cache.h                 |  8 +++++
 6 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 48fb19408cc10e99b79308debb7ef6c3e6bc0127..2b3bca892a5b9c483d1f6f099fd4a6493e9afcab 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -124,6 +124,15 @@ static int nss_clear_memcache(struct sbus_request *dbus_req, void *data)
         return ret;
     }
 
+    ret = sss_mmap_cache_reinit(nctx, SSS_MC_CACHE_ELEMENTS,
+                                (time_t)memcache_timeout,
+                                &nctx->initgr_mc_ctx);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "initgroups mmap cache invalidation failed\n");
+        return ret;
+    }
+
 done:
     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
 }
@@ -517,6 +526,13 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
         DEBUG(SSSDBG_CRIT_FAILURE, "group mmap cache is DISABLED\n");
     }
 
+    ret = sss_mmap_cache_init(nctx, "initgroups", SSS_MC_INITGROUPS,
+                              SSS_MC_CACHE_ELEMENTS, (time_t)memcache_timeout,
+                              &nctx->initgr_mc_ctx);
+    if (ret) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "inigroups mmap cache is DISABLED\n");
+    }
+
     /* Set up file descriptor limits */
     ret = confdb_get_int(nctx->rctx->cdb,
                          CONFDB_NSS_CONF_ENTRY,
diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
index 784eba2e0c6b15b106a2323bba1de5523e2937c1..e293e3b4d03582abf6abf07cce61d3b6fdebfcae 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -72,6 +72,7 @@ struct nss_ctx {
 
     struct sss_mc_ctx *pwd_mc_ctx;
     struct sss_mc_ctx *grp_mc_ctx;
+    struct sss_mc_ctx *initgr_mc_ctx;
 
     struct sss_idmap_ctx *idmap_ctx;
     struct sss_names_ctx *global_names;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index 012c4e701a4ee211e8e3bb66713d7edc43a48717..ccb8e733419c6c199d89f9a02bd1de93bb4b667c 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -3909,17 +3909,23 @@ done:
 
 /* FIXME: what about mpg, should we return the user's GID ? */
 /* FIXME: should we filter out GIDs ? */
-static int fill_initgr(struct sss_packet *packet, struct sss_domain_info *dom,
-                       struct ldb_result *res)
+static int fill_initgr(struct sss_packet *packet,
+                       struct sss_domain_info *dom,
+                       struct ldb_result *res,
+                       struct nss_ctx *nctx,
+                       const char *name)
 {
     uint8_t *body;
     size_t blen;
     gid_t gid;
-    int ret, i, num;
+    int ret, i;
+    uint32_t num;
     size_t bindex;
     int skipped = 0;
     const char *posix;
     gid_t orig_primary_gid;
+    struct sized_string rawname;
+    uint8_t *gids;
 
     if (res->count == 0) {
         return ENOENT;
@@ -3952,6 +3958,7 @@ static int fill_initgr(struct sss_packet *packet, struct sss_domain_info *dom,
     /* 0-3: 32bit unsigned number of results
      * 4-7: 32bit unsigned (reserved/padding) */
     bindex = 2 * sizeof(uint32_t);
+    gids = body + bindex;
 
     /* skip first entry, it's the user entry */
     for (i = 0; i < num; i++) {
@@ -3993,6 +4000,17 @@ static int fill_initgr(struct sss_packet *packet, struct sss_domain_info *dom,
         return ret;
     }
 
+    if (nctx->initgr_mc_ctx) {
+        to_sized_string(&rawname, name);
+        ret = sss_mmap_cache_initgr_store(&nctx->initgr_mc_ctx, &rawname,
+                                          num - skipped, gids);
+        if (ret != EOK && ret != ENOMEM) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Failed to store user %s(%s) in mmap cache!\n",
+                  rawname.str, dom->name);
+        }
+    }
+
     return EOK;
 }
 
@@ -4000,8 +4018,11 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx)
 {
     struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
     struct cli_ctx *cctx = cmdctx->cctx;
+    struct nss_ctx *nctx;
     int ret;
 
+    nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
+
     ret = sss_packet_new(cctx->creq, 0,
                          sss_packet_get_cmd(cctx->creq->in),
                          &cctx->creq->out);
@@ -4009,7 +4030,8 @@ static int nss_cmd_initgr_send_reply(struct nss_dom_ctx *dctx)
         return EFAULT;
     }
 
-    ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res);
+    ret = fill_initgr(cctx->creq->out, dctx->domain, dctx->res, nctx,
+                      dctx->rawname);
     if (ret) {
         return ret;
     }
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 18f83e1666953d146a80d2dee48d65e0ca41ed6a..b139c92c13ed80dc05a35f15963e733d46e2949a 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -31,6 +31,8 @@
 #define SSS_AVG_PASSWD_PAYLOAD (MC_SLOT_SIZE * 4)
 /* short group name and no gids (private user group */
 #define SSS_AVG_GROUP_PAYLOAD (MC_SLOT_SIZE * 3)
+/* average place for 40 supplementary groups */
+#define SSS_AVG_INITGROUP_PAYLOAD (MC_SLOT_SIZE * 4)
 
 #define MC_NEXT_BARRIER(val) ((((val) + 1) & 0x00ffffff) | 0xf0000000)
 
@@ -953,6 +955,65 @@ done:
     return ret;
 }
 
+errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                    struct sized_string *name,
+                                    uint32_t memnum,
+                                    uint8_t *membuf)
+{
+    struct sss_mc_ctx *mcc = *_mcc;
+    struct sss_mc_rec *rec;
+    struct sss_mc_initgr_data *data;
+    size_t data_len;
+    size_t rec_len;
+    int ret;
+
+    if (mcc == NULL) {
+        /* cache not initialized ? */
+        return EINVAL;
+    }
+
+    /* memnum + reserved + array of members + name*/
+    data_len = (2 + memnum) * sizeof(uint32_t) + name->len;
+    rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_initgr_data)
+              + data_len;
+    if (rec_len > mcc->dt_size) {
+        return ENOMEM;
+    }
+
+    ret = sss_mc_get_record(_mcc, rec_len, name, &rec);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    data = (struct sss_mc_initgr_data *)rec->data;
+
+    MC_RAISE_BARRIER(rec);
+
+    /* We cannot use two keys for searching in intgroups cache.
+     * Use the first key twice.
+     */
+    sss_mmap_set_rec_header(mcc, rec, rec_len, mcc->valid_time_slot,
+                            name->str, name->len, name->str, name->len);
+
+    /* initgroups struct */
+    data->members = memnum;
+    memcpy(data->gids, membuf, memnum * sizeof(uint32_t));
+    memcpy(&data->gids[memnum], name->str, name->len);
+    data->name = MC_PTR_DIFF(&data->gids[memnum], data);
+
+    MC_LOWER_BARRIER(rec);
+
+    /* finally chain the rec in the hash table */
+    sss_mmap_chain_in_rec(mcc, rec);
+
+    return EOK;
+}
+
+errno_t sss_mmap_cache_initgr_invalidate(struct sss_mc_ctx *mcc,
+                                         struct sized_string *name)
+{
+    return sss_mmap_cache_invalidate(mcc, name);
+}
 
 /***************************************************************************
  * initialization
@@ -1143,6 +1204,9 @@ errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
     case SSS_MC_GROUP:
         payload = SSS_AVG_GROUP_PAYLOAD;
         break;
+    case SSS_MC_INITGROUPS:
+        payload = SSS_AVG_INITGROUP_PAYLOAD;
+        break;
     default:
         return EINVAL;
     }
diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
index fdeaa09126858b04958f4e3eee17b8a92cf61350..3a6764dd36bf3346d789bb287b3a94df120f36ee 100644
--- a/src/responder/nss/nsssrv_mmap_cache.h
+++ b/src/responder/nss/nsssrv_mmap_cache.h
@@ -30,6 +30,7 @@ enum sss_mc_type {
     SSS_MC_NONE = 0,
     SSS_MC_PASSWD,
     SSS_MC_GROUP,
+    SSS_MC_INITGROUPS,
 };
 
 errno_t sss_mmap_cache_init(TALLOC_CTX *mem_ctx, const char *name,
@@ -50,6 +51,11 @@ errno_t sss_mmap_cache_gr_store(struct sss_mc_ctx **_mcc,
                                 gid_t gid, size_t memnum,
                                 char *membuf, size_t memsize);
 
+errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
+                                    struct sized_string *name,
+                                    uint32_t memnum,
+                                    uint8_t *membuf);
+
 errno_t sss_mmap_cache_pw_invalidate(struct sss_mc_ctx *mcc,
                                      struct sized_string *name);
 
@@ -60,6 +66,9 @@ errno_t sss_mmap_cache_gr_invalidate(struct sss_mc_ctx *mcc,
 
 errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid);
 
+errno_t sss_mmap_cache_initgr_invalidate(struct sss_mc_ctx *mcc,
+                                         struct sized_string *name);
+
 errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
                               time_t timeout, struct sss_mc_ctx **mc_ctx);
 
diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
index 81269fe7e03f586059aab789336ebe3903026d0a..438e28a3d217041278fc1bb60aa553d098516035 100644
--- a/src/util/mmap_cache.h
+++ b/src/util/mmap_cache.h
@@ -136,6 +136,14 @@ struct sss_mc_grp_data {
                              * string is zero terminated ordered as follows:
                              * name, passwd, member1, member2, ... */
 };
+
+struct sss_mc_initgr_data {
+    rel_ptr_t name;         /* ptr to name string, rel. to struct base addr */
+    uint32_t members;       /* number of members in groups */
+    uint32_t gids[0];       /* array of all groups
+                             * string with name is stored after gids */
+};
+
 #pragma pack()
 
 
-- 
2.4.3

-------------- next part --------------
>From 28d7087c0ee2c39db7d78c5bad6bed16162843cf Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 30 Jun 2015 14:16:47 +0200
Subject: [PATCH 3/8] mmap_cache: Invalidate entry in right memory cache

If group was not found in nss_cmd_getgrnam_search
then we tied to invalidate entry in memory cache.
But function delete_entry_from_memory cache only invalidated
in passwd memory cache.
---
 src/responder/nss/nsssrv_cmd.c | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index ccb8e733419c6c199d89f9a02bd1de93bb4b667c..b163d6d57b77d39999085d5d20b6c483e6b99448 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -753,7 +753,8 @@ static void nsssrv_dp_send_acct_req_done(struct tevent_req *req)
 }
 
 static int delete_entry_from_memcache(struct sss_domain_info *dom, char *name,
-                                      struct sss_mc_ctx *mc_ctx)
+                                      struct sss_mc_ctx *mc_ctx,
+                                      enum sss_mc_type type)
 {
     TALLOC_CTX *tmp_ctx = NULL;
     struct sized_string delete_name;
@@ -778,11 +779,27 @@ static int delete_entry_from_memcache(struct sss_domain_info *dom, char *name,
         to_sized_string(&delete_name, name);
     }
 
-    ret = sss_mmap_cache_pw_invalidate(mc_ctx, &delete_name);
-    if (ret != EOK && ret != ENOENT) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              "Internal failure in memory cache code: %d [%s]\n",
-               ret, strerror(ret));
+    switch (type) {
+    case SSS_MC_PASSWD:
+        ret = sss_mmap_cache_pw_invalidate(mc_ctx, &delete_name);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Internal failure in memory cache code: %d [%s]\n",
+                  ret, strerror(ret));
+            goto done;
+        }
+        break;
+    case SSS_MC_GROUP:
+        ret = sss_mmap_cache_gr_invalidate(mc_ctx, &delete_name);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Internal failure in memory cache code: %d [%s]\n",
+                  ret, strerror(ret));
+            goto done;
+        }
+        break;
+    default:
+        ret = EINVAL;
         goto done;
     }
 
@@ -944,7 +961,7 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
 
             /* User not found in ldb -> delete user from memory cache. */
             ret = delete_entry_from_memcache(dctx->domain, name,
-                                             nctx->pwd_mc_ctx);
+                                             nctx->pwd_mc_ctx, SSS_MC_PASSWD);
             if (ret != EOK) {
                 DEBUG(SSSDBG_MINOR_FAILURE,
                       "Deleting user from memcache failed.\n");
@@ -3064,7 +3081,7 @@ static int nss_cmd_getgrnam_search(struct nss_dom_ctx *dctx)
 
             /* Group not found in ldb -> delete group from memory cache. */
             ret = delete_entry_from_memcache(dctx->domain, name,
-                                             nctx->grp_mc_ctx);
+                                             nctx->grp_mc_ctx, SSS_MC_GROUP);
             if (ret != EOK) {
                 DEBUG(SSSDBG_MINOR_FAILURE,
                       "Deleting group from memcache failed.\n");
-- 
2.4.3

-------------- next part --------------
>From ebaa3cd69b8f676a8098fab88f1a7f65492ac32d Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 30 Jun 2015 14:26:12 +0200
Subject: [PATCH 4/8] nss: Invalidate entry in initgr mmap cache

If user is removed from sysdb cache then
it should be also removed from initgroups memory cache.

Resolves:
https://fedorahosted.org/sssd/ticket/2485
---
 src/responder/nss/nsssrv_cmd.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index b163d6d57b77d39999085d5d20b6c483e6b99448..0129467302f16af318bbbb0a5be47ff2e235da65 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -168,6 +168,13 @@ void nss_update_pw_memcache(struct nss_ctx *nctx)
                       "Internal failure in memory cache code: %d [%s]\n",
                        ret, strerror(ret));
             }
+
+            ret = sss_mmap_cache_pw_invalidate(nctx->initgr_mc_ctx, &key);
+            if (ret != EOK && ret != ENOENT) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "Internal failure in memory cache code: %d [%s]\n",
+                      ret, strerror(ret));
+            }
         }
 
         talloc_zfree(res);
@@ -798,6 +805,15 @@ static int delete_entry_from_memcache(struct sss_domain_info *dom, char *name,
             goto done;
         }
         break;
+    case SSS_MC_INITGROUPS:
+        ret = sss_mmap_cache_initgr_invalidate(mc_ctx, &delete_name);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Internal failure in memory cache code: %d [%s]\n",
+                  ret, strerror(ret));
+            goto done;
+        }
+        break;
     default:
         ret = EINVAL;
         goto done;
@@ -967,6 +983,14 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx)
                       "Deleting user from memcache failed.\n");
             }
 
+            ret = delete_entry_from_memcache(dctx->domain, name,
+                                             nctx->initgr_mc_ctx,
+                                             SSS_MC_INITGROUPS);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_MINOR_FAILURE,
+                      "Deleting user from memcache failed.\n");
+            }
+
             return ENOENT;
         }
 
@@ -3871,6 +3895,14 @@ void nss_update_initgr_memcache(struct nss_ctx *nctx,
                   ret, strerror(ret));
         }
 
+        ret = sss_mmap_cache_initgr_invalidate(nctx->initgr_mc_ctx,
+                                               &delete_name);
+        if (ret != EOK && ret != ENOENT) {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "Internal failure in memory cache code: %d [%s]\n",
+                  ret, strerror(ret));
+        }
+
         /* Also invalidate his groups */
         changed = true;
     } else {
-- 
2.4.3

-------------- next part --------------
>From 5d7bddd6188efd071eaa85c0d056861cb59a81e4 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 30 Jun 2015 16:36:03 +0200
Subject: [PATCH 5/8] sss_client: Use initgr mmap cache in client code

Resolves:
https://fedorahosted.org/sssd/ticket/2485
---
 Makefile.am                    |   1 +
 src/sss_client/nss_group.c     |  29 +++++++-
 src/sss_client/nss_mc.h        |   5 ++
 src/sss_client/nss_mc_initgr.c | 159 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100644 src/sss_client/nss_mc_initgr.c

diff --git a/Makefile.am b/Makefile.am
index 93a32dbdb932fe18c6d8f9361d7f97b0e05d0c17..6294a74f93a2d08f9374720a1ce9bc5f6a84f4c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2597,6 +2597,7 @@ libnss_sss_la_SOURCES = \
     src/util/murmurhash3.c \
     src/sss_client/nss_mc_passwd.c \
     src/sss_client/nss_mc_group.c \
+    src/sss_client/nss_mc_initgr.c \
     src/sss_client/nss_mc.h
 libnss_sss_la_LIBADD = \
     $(CLIENT_LIBS)
diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c
index 1614c33b5388326d82f1c9c1baaeee472a676cb9..b614fcf7f493345f793d3d4a28df998534ca546b 100644
--- a/src/sss_client/nss_group.c
+++ b/src/sss_client/nss_group.c
@@ -281,10 +281,37 @@ enum nss_status _nss_sss_initgroups_dyn(const char *user, gid_t group,
     size_t replen;
     enum nss_status nret;
     size_t buf_index = 0;
+    size_t user_len;
     uint32_t num_ret;
     long int l, max_ret;
+    int ret;
 
-    rd.len = strlen(user) +1;
+    ret = sss_strnlen(user, SSS_NAME_MAX, &user_len);
+    if (ret != 0) {
+        *errnop = EINVAL;
+        return NSS_STATUS_NOTFOUND;
+    }
+
+    ret = sss_nss_mc_initgroups_dyn(user, user_len, group, start, size,
+                                    groups, limit);
+    switch (ret) {
+    case 0:
+        *errnop = 0;
+        return NSS_STATUS_SUCCESS;
+    case ERANGE:
+        *errnop = ERANGE;
+        return NSS_STATUS_TRYAGAIN;
+    case ENOENT:
+        /* fall through, we need to actively ask the parent
+         * if no entry is found */
+        break;
+    default:
+        /* if using the mmaped cache failed,
+         * fall back to socket based comms */
+        break;
+    }
+
+    rd.len = user_len + 1;
     rd.data = user;
 
     sss_nss_lock();
diff --git a/src/sss_client/nss_mc.h b/src/sss_client/nss_mc.h
index 050bd4100dec091cb096a7d97bfe6615b12654da..a39d45f143d2f2a6eb006ffc4b45fda097dad4f2 100644
--- a/src/sss_client/nss_mc.h
+++ b/src/sss_client/nss_mc.h
@@ -85,4 +85,9 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
                             struct group *result,
                             char *buffer, size_t buflen);
 
+/* initgroups db */
+errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+                                  gid_t group, long int *start, long int *size,
+                                  gid_t **groups, long int limit);
+
 #endif /* _NSS_MC_H_ */
diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..bfb09d6550c310fbab254dc9b3ab7b306b7d3f06
--- /dev/null
+++ b/src/sss_client/nss_mc_initgr.c
@@ -0,0 +1,159 @@
+/*
+ * System Security Services Daemon. NSS client interface
+ *
+ * Authors:
+ *     Lukas Slebodnik <lslebodn at redhat.com>
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* INITGROUPs database NSS interface using mmap cache */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/mman.h>
+#include <time.h>
+#include "nss_mc.h"
+#include "util/util_safealign.h"
+
+struct sss_cli_mc_ctx initgr_mc_ctx = { UNINITIALIZED, -1, 0, NULL, 0, NULL, 0,
+                                        NULL, 0, 0 };
+
+static errno_t sss_nss_mc_parse_result(struct sss_mc_rec *rec,
+                                       long int *start, long int *size,
+                                       gid_t **groups, long int limit)
+{
+    struct sss_mc_initgr_data *data;
+    time_t expire;
+    long int i;
+    uint32_t gid_count;
+    long int max_ret;
+
+    /* additional checks before filling result*/
+    expire = rec->expire;
+    if (expire < time(NULL)) {
+        /* entry is now invalid */
+        return EINVAL;
+    }
+
+    data = (struct sss_mc_initgr_data *)rec->data;
+    gid_count = data->members;
+    max_ret = gid_count;
+
+    /* check we have enough space in the buffer */
+    if ((*size - *start) < gid_count) {
+        long int newsize;
+        gid_t *newgroups;
+
+        newsize = *size + gid_count;
+        if ((limit > 0) && (newsize > limit)) {
+            newsize = limit;
+            max_ret = newsize - *start;
+        }
+
+        newgroups = (gid_t *)realloc((*groups), newsize * sizeof(**groups));
+        if (!newgroups) {
+            return ENOMEM;
+        }
+        *groups = newgroups;
+        *size = newsize;
+    }
+
+    for (i = 0; i < max_ret; i++) {
+        SAFEALIGN_COPY_UINT32(&(*groups)[*start], data->gids + i, NULL);
+        *start += 1;
+    }
+
+    return 0;
+}
+
+errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
+                                  gid_t group, long int *start, long int *size,
+                                  gid_t **groups, long int limit)
+{
+    struct sss_mc_rec *rec = NULL;
+    struct sss_mc_initgr_data *data;
+    char *rec_name;
+    uint32_t hash;
+    uint32_t slot;
+    int ret;
+    uint8_t *max_addr;
+
+    ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx);
+    if (ret) {
+        return ret;
+    }
+
+    /* Get max address of data table. */
+    max_addr = initgr_mc_ctx.data_table + initgr_mc_ctx.dt_size;
+
+    /* hashes are calculated including the NULL terminator */
+    hash = sss_nss_mc_hash(&initgr_mc_ctx, name, name_len + 1);
+    slot = initgr_mc_ctx.hash_table[hash];
+
+    /* If slot is not within the bounds of mmaped region and
+     * it's value is not MC_INVALID_VAL, then the cache is
+     * probbably corrupted. */
+    while (MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
+        /* free record from previous iteration */
+        free(rec);
+        rec = NULL;
+
+        ret = sss_nss_mc_get_record(&initgr_mc_ctx, slot, &rec);
+        if (ret) {
+            goto done;
+        }
+
+        /* check record matches what we are searching for */
+        if (hash != rec->hash1) {
+            /* if name hash does not match we can skip this immediately */
+            slot = sss_nss_mc_next_slot_with_hash(rec, hash);
+            continue;
+        }
+
+        data = (struct sss_mc_initgr_data *)rec->data;
+        /* Integrity check
+         * - array with gids must be within data_table
+         * - string must be within data_table */
+        if ((uint8_t *)data->gids > max_addr
+                || (uint8_t *)data + data->name + name_len > max_addr) {
+            ret = ENOENT;
+            goto done;
+        }
+
+        rec_name = (char *)data + data->name;
+        if (strcmp(name, rec_name) == 0) {
+            break;
+        }
+
+        slot = sss_nss_mc_next_slot_with_hash(rec, hash);
+    }
+
+    if (!MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
+        ret = ENOENT;
+        goto done;
+    }
+
+    ret = sss_nss_mc_parse_result(rec, start, size, groups, limit);
+
+done:
+    free(rec);
+    __sync_sub_and_fetch(&initgr_mc_ctx.active_threads, 1);
+    return ret;
+}
-- 
2.4.3

-------------- next part --------------
>From 5220df784928ea6c79322f67712b083998b019c1 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 30 Jun 2015 17:43:34 +0200
Subject: [PATCH 6/8] sss_cache: Clear also initgroups fast cache

---
 src/tools/tools_mc_util.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/tools/tools_mc_util.c b/src/tools/tools_mc_util.c
index 9634b86e248a1937f68939c5a8d8a6301780a566..c1b5c616d0e6d50147ecd81308aaa1e69304af92 100644
--- a/src/tools/tools_mc_util.c
+++ b/src/tools/tools_mc_util.c
@@ -147,6 +147,16 @@ static int clear_fastcache(bool *sssd_nss_is_off)
         }
     }
 
+    ret = sss_memcache_invalidate(SSS_NSS_MCACHE_DIR"/initgroups");
+    if (ret != EOK) {
+        if (ret == EACCES) {
+            *sssd_nss_is_off = false;
+            return EOK;
+        } else {
+            return ret;
+        }
+    }
+
     *sssd_nss_is_off = true;
     return EOK;
 }
-- 
2.4.3



More information about the sssd-devel mailing list