summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Slebodnik <lslebodn@redhat.com>2015-07-16 17:00:12 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-08-05 11:28:19 +0200
commit225dc6914cdc8920b02a129b98ece1ed97b99c03 (patch)
tree39ef3e048f6460b4f70001197e25b1b8d14b4193
parent39b31427e2d11ca318df11fd48db33a7cc610aa7 (diff)
downloadsssd-225dc6914cdc8920b02a129b98ece1ed97b99c03.tar.gz
sssd-225dc6914cdc8920b02a129b98ece1ed97b99c03.tar.xz
sssd-225dc6914cdc8920b02a129b98ece1ed97b99c03.zip
mmap_cache: "Override" functions for initgr mmap cache
Functions sss_mc_get_strs_offset and sss_mc_get_strs_len provides data about strings for individual memory caches (passwd, ...) Their are used in generic responder mmap cache code to find a record in mmap cache (sss_mc_find_record). Data provided from functions sss_mc_get_* are used for checking the validity of record. So in case of corrupted record the whole mmap cache can be invalidated. Functions sss_mc_get_strs_offset and sss_mc_get_strs_len did not provide data for initgroups mmap cache and therefore particular record could not be invalidated. Resolves: https://fedorahosted.org/sssd/ticket/2716 Reviewed-by: Michal Židek <mzidek@redhat.com>
-rw-r--r--src/responder/nss/nsssrv_mmap_cache.c15
-rw-r--r--src/sss_client/nss_mc_initgr.c16
-rw-r--r--src/util/mmap_cache.h6
3 files changed, 28 insertions, 9 deletions
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 16bc926f3..ab9e769b1 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -475,6 +475,9 @@ static errno_t sss_mc_get_strs_offset(struct sss_mc_ctx *mcc,
case SSS_MC_GROUP:
*_offset = offsetof(struct sss_mc_grp_data, strs);
return EOK;
+ case SSS_MC_INITGROUPS:
+ *_offset = offsetof(struct sss_mc_initgr_data, gids);
+ return EOK;
default:
DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
return EINVAL;
@@ -492,6 +495,9 @@ static errno_t sss_mc_get_strs_len(struct sss_mc_ctx *mcc,
case SSS_MC_GROUP:
*_len = ((struct sss_mc_grp_data *)&rec->data)->strs_len;
return EOK;
+ case SSS_MC_INITGROUPS:
+ *_len = ((struct sss_mc_initgr_data *)&rec->data)->data_len;
+ return EOK;
default:
DEBUG(SSSDBG_FATAL_FAILURE, "Unknown memory cache type.\n");
return EINVAL;
@@ -974,8 +980,8 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
return EINVAL;
}
- /* num_groups + reserved + array of gids + name*/
- data_len = (2 + num_groups) * sizeof(uint32_t) + name->len;
+ /* array of gids + name */
+ data_len = num_groups * 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) {
@@ -998,10 +1004,13 @@ errno_t sss_mmap_cache_initgr_store(struct sss_mc_ctx **_mcc,
name->str, name->len, name->str, name->len);
/* initgroups struct */
+ data->strs_len = name->len;
+ data->data_len = data_len;
+ data->reserved = MC_INVALID_VAL32;
data->num_groups = num_groups;
memcpy(data->gids, gids_buf, num_groups * sizeof(uint32_t));
memcpy(&data->gids[num_groups], name->str, name->len);
- data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
+ data->strs = data->name = MC_PTR_DIFF(&data->gids[num_groups], data);
MC_LOWER_BARRIER(rec);
diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
index e21b9f40a..153617ea9 100644
--- a/src/sss_client/nss_mc_initgr.c
+++ b/src/sss_client/nss_mc_initgr.c
@@ -93,6 +93,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
uint32_t hash;
uint32_t slot;
int ret;
+ const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids);
uint8_t *max_addr;
ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx);
@@ -128,16 +129,21 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
}
data = (struct sss_mc_initgr_data *)rec->data;
+ rec_name = (char *)data + data->name;
/* 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) {
+ * - name_len cannot be longer than all strings or data
+ * - data->name cannot point outside strings
+ * - all data must be within data_table
+ * - name must be within data_table */
+ if (name_len > data->data_len
+ || name_len > data->strs_len
+ || (data->strs + name_len) > (data_offset + data->data_len)
+ || (uint8_t *)data->gids + data->data_len > max_addr
+ || (uint8_t *)rec_name + name_len > max_addr) {
ret = ENOENT;
goto done;
}
- rec_name = (char *)data + data->name;
if (strcmp(name, rec_name) == 0) {
break;
}
diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
index a8703d5da..b5917b3c0 100644
--- a/src/util/mmap_cache.h
+++ b/src/util/mmap_cache.h
@@ -79,7 +79,7 @@ typedef uint32_t rel_ptr_t;
#define SSS_MC_MAJOR_VNO 1
-#define SSS_MC_MINOR_VNO 0
+#define SSS_MC_MINOR_VNO 1
#define SSS_MC_HEADER_UNINIT 0 /* after ftruncate or before reset */
#define SSS_MC_HEADER_ALIVE 1 /* current and in use */
@@ -139,6 +139,10 @@ struct sss_mc_grp_data {
struct sss_mc_initgr_data {
rel_ptr_t name; /* ptr to name string, rel. to struct base addr */
+ rel_ptr_t strs; /* ptr to concatenation of all strings */
+ uint32_t reserved;
+ uint32_t strs_len; /* length of strs */
+ uint32_t data_len; /* all initgroups data len */
uint32_t num_groups; /* number of groups */
uint32_t gids[0]; /* array of all groups
* string with name is stored after gids */