[SSSD] [PATCHES] The fast memory cache should cache initgroups
Lukas Slebodnik
lslebodn at redhat.com
Tue Jun 30 21:10:09 UTC 2015
ehlo,
patches are attached.
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 b3d1e4ca0da29271f8dedc32b0afaa6e3ed34855 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 | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index b163d6d57b77d39999085d5d20b6c483e6b99448..412cd1c17ebfe43189c4685a5ad351f9844821e6 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);
@@ -797,6 +804,14 @@ static int delete_entry_from_memcache(struct sss_domain_info *dom, char *name,
ret, strerror(ret));
goto done;
}
+ 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;
@@ -967,6 +982,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 +3894,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 e63ec2b0e2ff4078ba1c36aa6e5466d87906440e 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 e921a1ec890087ac0d493879610893532813d0de 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