diff options
author | Michal Zidek <mzidek@redhat.com> | 2013-08-05 20:59:33 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2013-08-11 20:36:21 +0200 |
commit | 9028706a00da1bc48547e74aa872c825ac15adb2 (patch) | |
tree | c1133d5686c5a8e6922920ca829c26dde7182561 /src | |
parent | 86c985481c2fdb1d8996a77576b12bff431c18d5 (diff) | |
download | sssd-9028706a00da1bc48547e74aa872c825ac15adb2.tar.gz sssd-9028706a00da1bc48547e74aa872c825ac15adb2.tar.xz sssd-9028706a00da1bc48547e74aa872c825ac15adb2.zip |
mmap_cache: Check if slot and name_ptr are not invalid.
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
Diffstat (limited to 'src')
-rw-r--r-- | src/responder/nss/nsssrv_mmap_cache.c | 54 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_mmap_cache.h | 2 | ||||
-rw-r--r-- | src/sss_client/nss_mc_group.c | 8 | ||||
-rw-r--r-- | src/sss_client/nss_mc_passwd.c | 8 | ||||
-rw-r--r-- | src/util/mmap_cache.h | 3 |
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 49878fcfb..cd5a6436e 100644 --- a/src/responder/nss/nsssrv_mmap_cache.c +++ b/src/responder/nss/nsssrv_mmap_cache.c @@ -373,8 +373,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) { @@ -608,6 +623,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); @@ -739,6 +761,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); @@ -889,8 +918,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); @@ -1113,3 +1143,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 b3e9a8a0b..2d69be93b 100644 --- a/src/sss_client/nss_mc_group.c +++ b/src/sss_client/nss_mc_group.c @@ -116,6 +116,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) { @@ -180,6 +184,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 4acc6425e..fa21bd289 100644 --- a/src/sss_client/nss_mc_passwd.c +++ b/src/sss_client/nss_mc_passwd.c @@ -117,6 +117,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) { @@ -181,6 +185,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 55383c056..6c223df6c 100644 --- a/src/util/mmap_cache.h +++ b/src/util/mmap_cache.h @@ -78,6 +78,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 */ @@ -109,6 +110,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; |