>From a2dd2ecbfb9c066f191c5541bb775657bc0d25db Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Fri, 13 Sep 2013 17:41:28 +0200
Subject: [PATCH] Check slot validity before MC_SLOT_TO_PTR.

---
 src/responder/nss/nsssrv_mmap_cache.c | 49 +++++++++++++++++++++++++++++++++++
 src/sss_client/nss_mc_common.c        |  4 +++
 2 files changed, 53 insertions(+)

diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 4e45405..25510ae 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -191,6 +191,14 @@ static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc,
     }
 
     do {
+        if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                  ("Corrupted fastcache. Slot number too big.\n"));
+            sss_mc_save_corrupted(mcc);
+            sss_mmap_cache_reset(mcc);
+            return;
+        }
+
         cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
         if (cur == rec) {
             /* rec already stored in hash chain */
@@ -215,6 +223,14 @@ sss_mc_get_next_slot_with_hash(struct sss_mc_ctx *mcc,
 
     slot = start_rec->next;
     while (slot != MC_INVALID_VAL) {
+        if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                  ("Corrupted fastcache. Slot number too big.\n"));
+            sss_mc_save_corrupted(mcc);
+            sss_mmap_cache_reset(mcc);
+            return MC_INVALID_VAL;
+        }
+
         rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
         if (rec->hash1 == hash || rec->hash2 == hash) {
             break;
@@ -249,6 +265,15 @@ static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc,
          */
         return;
     }
+
+    if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Corrupted fastcache. Slot number too big.\n"));
+        sss_mc_save_corrupted(mcc);
+        sss_mmap_cache_reset(mcc);
+        return;
+    }
+
     cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
     if (cur == rec) {
         /* rec->next can refer to record without matching hashes.
@@ -259,6 +284,14 @@ static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc,
     } else {
         slot = cur->next;
         while (slot != MC_INVALID_VAL) {
+            if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+                DEBUG(SSSDBG_FATAL_FAILURE,
+                      ("Corrupted fastcache. Slot number too big.\n"));
+                sss_mc_save_corrupted(mcc);
+                sss_mmap_cache_reset(mcc);
+                return;
+            }
+
             prev = cur;
             cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
             if (cur == rec) {
@@ -353,6 +386,14 @@ static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
         self = NULL;
         slot = mcc->hash_table[rec->hash1];
         while (slot != MC_INVALID_VAL32 && self != rec) {
+            if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+                DEBUG(SSSDBG_FATAL_FAILURE,
+                      ("Corrupted fastcache. Slot number too big.\n"));
+                sss_mc_save_corrupted(mcc);
+                sss_mmap_cache_reset(mcc);
+                return false;
+            }
+
             self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
             slot = self->next;
         }
@@ -364,6 +405,14 @@ static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
         self = NULL;
         slot = mcc->hash_table[rec->hash2];
         while (slot != MC_INVALID_VAL32 && self != rec) {
+            if (!MC_SLOT_WITHIN_BOUNDS(slot, mcc->dt_size)) {
+                DEBUG(SSSDBG_FATAL_FAILURE,
+                      ("Corrupted fastcache. Slot number too big.\n"));
+                sss_mc_save_corrupted(mcc);
+                sss_mmap_cache_reset(mcc);
+                return false;
+            }
+
             self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
             slot = self->next;
         }
diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c
index 5d36c47..f8a6b3b 100644
--- a/src/sss_client/nss_mc_common.c
+++ b/src/sss_client/nss_mc_common.c
@@ -190,6 +190,10 @@ errno_t sss_nss_mc_get_record(struct sss_cli_mc_ctx *ctx,
     int count;
     int ret;
 
+    if (!MC_SLOT_WITHIN_BOUNDS(slot, ctx->dt_size)) {
+        return EINVAL;
+    }
+
     /* try max 5 times */
     for (count = 5; count > 0; count--) {
         rec = MC_SLOT_TO_PTR(ctx->data_table, slot, struct sss_mc_rec);
-- 
1.7.11.2

