summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Zidek <mzidek@redhat.com>2013-08-05 20:59:33 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-08-11 22:21:17 +0200
commitb5d6a9dc1ad63e8567de4c2805fc5baad54dc456 (patch)
tree4ee3d0db415ba34b1817570d9a9008e3e3e0e8fc
parent29b9dbc96370b85e460156e528cb2542c160cfd3 (diff)
downloadsssd-b5d6a9dc1ad63e8567de4c2805fc5baad54dc456.tar.gz
sssd-b5d6a9dc1ad63e8567de4c2805fc5baad54dc456.tar.xz
sssd-b5d6a9dc1ad63e8567de4c2805fc5baad54dc456.zip
mmap_cache: Check if slot and name_ptr are not invalid.sssd-1.9.2-118.el6
This patch prevents jumping outside of allocated memory in case of corrupted slot or name_ptr values. It is not proper solution, just hotfix until we find out what is the root cause of ticket https://fedorahosted.org/sssd/ticket/2018
-rw-r--r--src/responder/nss/nsssrv_mmap_cache.c54
-rw-r--r--src/responder/nss/nsssrv_mmap_cache.h2
-rw-r--r--src/sss_client/nss_mc_group.c8
-rw-r--r--src/sss_client/nss_mc_passwd.c8
-rw-r--r--src/util/mmap_cache.h3
5 files changed, 73 insertions, 2 deletions
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 8cf27ca69..02527dac4 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -374,8 +374,23 @@ static struct sss_mc_rec *sss_mc_find_record(struct sss_mc_ctx *mcc,
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Corrupted fastcache. Slot number too big.\n"));
+ sss_mmap_cache_reset(mcc);
+ return NULL;
+ }
+
rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
name_ptr = *((rel_ptr_t *)rec->data);
+ /* FIXME: This check relies on fact that offset of member strs
+ * is the same in structures sss_mc_pwd_data and sss_mc_group_data. */
+ if (name_ptr != offsetof(struct sss_mc_pwd_data, strs)) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ ("Corrupted fastcache. name_ptr value is %u.\n", name_ptr));
+ sss_mmap_cache_reset(mcc);
+ return NULL;
+ }
t_key = (char *)rec->data + name_ptr;
if (strcmp(key->str, t_key) == 0) {
@@ -579,6 +594,13 @@ errno_t sss_mmap_cache_pw_invalidate_uid(struct sss_mc_ctx *mcc, uid_t uid)
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Corrupted fastcache.\n"));
+ sss_mmap_cache_reset(mcc);
+ ret = ENOENT;
+ goto done;
+ }
+
rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
data = (struct sss_mc_pwd_data *)(&rec->data);
@@ -705,6 +727,13 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid)
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(mcc->dt_size)) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Corrupted fastcache.\n"));
+ sss_mmap_cache_reset(mcc);
+ ret = ENOENT;
+ goto done;
+ }
+
rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
data = (struct sss_mc_grp_data *)(&rec->data);
@@ -852,8 +881,9 @@ static void sss_mc_header_update(struct sss_mc_ctx *mc_ctx, int status)
/* update header using barriers */
h = (struct sss_mc_header *)mc_ctx->mmap_base;
MC_RAISE_BARRIER(h);
- if (status != SSS_MC_HEADER_RECYCLED) {
- /* no reason to update anything else if the file is recycled */
+ if (status == SSS_MC_HEADER_ALIVE) {
+ /* no reason to update anything else if the file is recycled or
+ * right before reset */
h->hash_table = MC_PTR_DIFF(mc_ctx->hash_table, mc_ctx->mmap_base);
h->free_table = MC_PTR_DIFF(mc_ctx->free_table, mc_ctx->mmap_base);
h->data_table = MC_PTR_DIFF(mc_ctx->data_table, mc_ctx->mmap_base);
@@ -1076,3 +1106,23 @@ done:
talloc_free(tmp_ctx);
return ret;
}
+
+/* Erase all contents of the mmap cache. This will bring the cache
+ * to the same state as if it was just initialized. */
+void sss_mmap_cache_reset(struct sss_mc_ctx *mc_ctx)
+{
+ if (mc_ctx == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("Fastcache not initialized. Nothing to do.\n"));
+ return;
+ }
+
+ sss_mc_header_update(mc_ctx, SSS_MC_HEADER_UNINIT);
+
+ /* Reset the mmaped area */
+ memset(mc_ctx->data_table, 0xff, mc_ctx->dt_size);
+ memset(mc_ctx->free_table, 0x00, mc_ctx->ft_size);
+ memset(mc_ctx->hash_table, 0xff, mc_ctx->ht_size);
+
+ sss_mc_header_update(mc_ctx, SSS_MC_HEADER_ALIVE);
+}
diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
index 25cec40cc..fdeaa0912 100644
--- a/src/responder/nss/nsssrv_mmap_cache.h
+++ b/src/responder/nss/nsssrv_mmap_cache.h
@@ -63,4 +63,6 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid);
errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem,
time_t timeout, struct sss_mc_ctx **mc_ctx);
+void sss_mmap_cache_reset(struct sss_mc_ctx *mc_ctx);
+
#endif /* _NSSSRV_MMAP_CACHE_H_ */
diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
index 7beeb2823..41d8d65a9 100644
--- a/src/sss_client/nss_mc_group.c
+++ b/src/sss_client/nss_mc_group.c
@@ -117,6 +117,10 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(gr_mc_ctx.dt_size)) {
+ /* This probably means that the memory cache was corrupted. */
+ return ENOENT;
+ }
ret = sss_nss_mc_get_record(&gr_mc_ctx, slot, &rec);
if (ret) {
@@ -181,6 +185,10 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(gr_mc_ctx.dt_size)) {
+ /* This probably means that the memory cache was corrupted. */
+ return ENOENT;
+ }
ret = sss_nss_mc_get_record(&gr_mc_ctx, slot, &rec);
if (ret) {
diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
index ca9945e4b..fb29b9750 100644
--- a/src/sss_client/nss_mc_passwd.c
+++ b/src/sss_client/nss_mc_passwd.c
@@ -118,6 +118,10 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(pw_mc_ctx.dt_size)) {
+ /* This probably means that the memory cache was corrupted */
+ return ENOENT;
+ }
ret = sss_nss_mc_get_record(&pw_mc_ctx, slot, &rec);
if (ret) {
@@ -182,6 +186,10 @@ errno_t sss_nss_mc_getpwuid(uid_t uid,
}
while (slot != MC_INVALID_VAL) {
+ if (slot > MC_SIZE_TO_SLOTS(pw_mc_ctx.dt_size)) {
+ /* This probably means that the memory cache was corrupted */
+ return ENOENT;
+ }
ret = sss_nss_mc_get_record(&pw_mc_ctx, slot, &rec);
if (ret) {
diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
index 407eeea69..5350a0eb3 100644
--- a/src/util/mmap_cache.h
+++ b/src/util/mmap_cache.h
@@ -73,6 +73,7 @@ typedef uint32_t rel_ptr_t;
#define SSS_MC_MAJOR_VNO 0
#define SSS_MC_MINOR_VNO 4
+#define SSS_MC_HEADER_UNINIT 0 /* after ftruncate or before reset */
#define SSS_MC_HEADER_ALIVE 1 /* current and in use */
#define SSS_MC_HEADER_RECYCLED 2 /* file was recycled, reopen asap */
@@ -104,6 +105,8 @@ struct sss_mc_rec {
char data[0];
};
+/* FIXME: Function sss_mc_find_record currently relies on fact that
+ * offset of strs is the same in both sss_mc_pwd_data and sss_mc_grp_data. */
struct sss_mc_pwd_data {
rel_ptr_t name; /* ptr to name string, rel. to struct base addr */
uint32_t uid;