>From 74b7282102f7d2be8690368f92ced68bd53135f8 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Mon, 19 Aug 2013 05:39:28 +0200 Subject: [PATCH] mmap_cache: Skip records which doesn't have same hash Record in data table has two hashes hash1 and hash2. Hash table refers to the first record with the searched hash key. We do a record chaining in case of hash collision. When we removed record from memory cache, entry in the hash_table was automaticaly updated to the next record from chain. But it is possible, that following record will have different hashes (hash1 and hash2). Therefore it can happen, that some hash table keys refers to records, which both hashes has different values like hash key. Such record can be removed from memory cache, but there will be reference in hash table with different key, which could not be removed, but it points to removed data or in the worst case it points in the middle of newly added record. And this was a reason of crash in nss. This patch fixes removing fix entry from chain. Resolves: https://fedorahosted.org/sssd/ticket/2018 --- src/responder/nss/nsssrv_mmap_cache.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c index cd5a6436e005b4c7f5622eaff2f259de3bbe5d29..aa9d535e404456c18eaf9e0b57557a77500cdbea 100644 --- a/src/responder/nss/nsssrv_mmap_cache.c +++ b/src/responder/nss/nsssrv_mmap_cache.c @@ -134,6 +134,27 @@ static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc, cur->next = MC_PTR_TO_SLOT(mcc->data_table, rec); } +static inline uint32_t +sss_mc_get_next_slot_with_hash(struct sss_mc_ctx *mcc, + struct sss_mc_rec *start_rec, + uint32_t hash) +{ + struct sss_mc_rec *rec; + uint32_t slot; + + slot = start_rec->next; + while (slot != MC_INVALID_VAL) { + rec = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec); + if (rec->hash1 == hash || rec->hash2 == hash) { + break; + } + + slot = rec->next; + } + + return slot; +} + static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec, uint32_t hash) @@ -151,7 +172,7 @@ static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc, slot = mcc->hash_table[hash]; cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec); if (cur == rec) { - mcc->hash_table[hash] = rec->next; + mcc->hash_table[hash] = sss_mc_get_next_slot_with_hash(mcc, rec, hash); } else { slot = cur->next; while (slot != MC_INVALID_VAL) { -- 1.8.3.1