|
|
6cf099 |
From e115f70d717ab8232172b358739ba7a0e1102caa Mon Sep 17 00:00:00 2001
|
|
|
6cf099 |
From: Lukas Slebodnik <lslebodn@redhat.com>
|
|
|
6cf099 |
Date: Thu, 30 Jul 2015 10:50:47 +0200
|
|
|
6cf099 |
Subject: [PATCH 41/47] sss_client: Update integrity check of records in mmap
|
|
|
6cf099 |
cache
|
|
|
6cf099 |
MIME-Version: 1.0
|
|
|
6cf099 |
Content-Type: text/plain; charset=UTF-8
|
|
|
6cf099 |
Content-Transfer-Encoding: 8bit
|
|
|
6cf099 |
|
|
|
6cf099 |
The function sss_nss_mc_get_record return copy of record from memory
|
|
|
6cf099 |
cache in last argument. Because we should not access data directly
|
|
|
6cf099 |
to avoid problems with consistency of record.
|
|
|
6cf099 |
The function sss_nss_mc_get_record also check whether length of record
|
|
|
6cf099 |
is within data area (with macro MC_CHECK_RECORD_LENGTH)
|
|
|
6cf099 |
|
|
|
6cf099 |
However we also tried to do the same check in functions sss_nss_mc_get{gr, pw}*
|
|
|
6cf099 |
Pointer to end of strings in record was compared to pointer to the end
|
|
|
6cf099 |
of data table. But these two pointers are not within the same allocated area
|
|
|
6cf099 |
and does not make sense to compare them. Sometimes record can be allocated
|
|
|
6cf099 |
before mmaped area and sometime after. Sometimes it will return cached data
|
|
|
6cf099 |
and other time will fall back to responder.
|
|
|
6cf099 |
|
|
|
6cf099 |
Resolves:
|
|
|
6cf099 |
https://fedorahosted.org/sssd/ticket/2743
|
|
|
6cf099 |
|
|
|
6cf099 |
Reviewed-by: Michal Židek <mzidek@redhat.com>
|
|
|
6cf099 |
(cherry picked from commit ba847347cade817ee927397d82c952b51b0dcb2b)
|
|
|
6cf099 |
---
|
|
|
6cf099 |
src/sss_client/nss_mc_group.c | 19 ++++++++++---------
|
|
|
6cf099 |
src/sss_client/nss_mc_initgr.c | 26 +++++++++++++-------------
|
|
|
6cf099 |
src/sss_client/nss_mc_passwd.c | 20 ++++++++++----------
|
|
|
6cf099 |
3 files changed, 33 insertions(+), 32 deletions(-)
|
|
|
6cf099 |
|
|
|
6cf099 |
diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
|
|
|
6cf099 |
index e0fdb97f628ac19741409be29566e4af5a391f74..aacf59d9fd8b81ea895f4660de08f3e44f0ce645 100644
|
|
|
6cf099 |
--- a/src/sss_client/nss_mc_group.c
|
|
|
6cf099 |
+++ b/src/sss_client/nss_mc_group.c
|
|
|
6cf099 |
@@ -112,16 +112,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
|
|
|
6cf099 |
uint32_t hash;
|
|
|
6cf099 |
uint32_t slot;
|
|
|
6cf099 |
int ret;
|
|
|
6cf099 |
- size_t strs_offset;
|
|
|
6cf099 |
- uint8_t *max_addr;
|
|
|
6cf099 |
+ const size_t strs_offset = offsetof(struct sss_mc_grp_data, strs);
|
|
|
6cf099 |
+ size_t data_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
ret = sss_nss_mc_get_ctx("group", &gr_mc_ctx);
|
|
|
6cf099 |
if (ret) {
|
|
|
6cf099 |
return ret;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- /* Get max address of data table. */
|
|
|
6cf099 |
- max_addr = gr_mc_ctx.data_table + gr_mc_ctx.dt_size;
|
|
|
6cf099 |
+ /* Get max size of data table. */
|
|
|
6cf099 |
+ data_size = gr_mc_ctx.dt_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
/* hashes are calculated including the NULL terminator */
|
|
|
6cf099 |
hash = sss_nss_mc_hash(&gr_mc_ctx, name, name_len + 1);
|
|
|
6cf099 |
@@ -130,7 +130,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
|
|
|
6cf099 |
/* If slot is not within the bounds of mmaped region and
|
|
|
6cf099 |
* it's value is not MC_INVALID_VAL, then the cache is
|
|
|
6cf099 |
* probbably corrupted. */
|
|
|
6cf099 |
- while (MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
/* free record from previous iteration */
|
|
|
6cf099 |
free(rec);
|
|
|
6cf099 |
rec = NULL;
|
|
|
6cf099 |
@@ -147,15 +147,16 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
|
|
|
6cf099 |
continue;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- strs_offset = offsetof(struct sss_mc_grp_data, strs);
|
|
|
6cf099 |
data = (struct sss_mc_grp_data *)rec->data;
|
|
|
6cf099 |
/* Integrity check
|
|
|
6cf099 |
* - name_len cannot be longer than all strings
|
|
|
6cf099 |
* - data->name cannot point outside strings
|
|
|
6cf099 |
- * - all strings must be within data_table */
|
|
|
6cf099 |
+ * - all strings must be within copy of record
|
|
|
6cf099 |
+ * - size of record must be lower that data table size */
|
|
|
6cf099 |
if (name_len > data->strs_len
|
|
|
6cf099 |
|| (data->name + name_len) > (strs_offset + data->strs_len)
|
|
|
6cf099 |
- || (uint8_t *)data->strs + data->strs_len > max_addr) {
|
|
|
6cf099 |
+ || data->strs_len > rec->len
|
|
|
6cf099 |
+ || rec->len > data_size) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
@@ -168,7 +169,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
|
|
|
6cf099 |
slot = sss_nss_mc_next_slot_with_hash(rec, hash);
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
diff --git a/src/sss_client/nss_mc_initgr.c b/src/sss_client/nss_mc_initgr.c
|
|
|
6cf099 |
index 153617ea9c6489b7439b9676904b42b042f6697c..74143d9fb3c674c3116d7f4cf0b4c03d993743a2 100644
|
|
|
6cf099 |
--- a/src/sss_client/nss_mc_initgr.c
|
|
|
6cf099 |
+++ b/src/sss_client/nss_mc_initgr.c
|
|
|
6cf099 |
@@ -94,15 +94,15 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
|
|
|
6cf099 |
uint32_t slot;
|
|
|
6cf099 |
int ret;
|
|
|
6cf099 |
const size_t data_offset = offsetof(struct sss_mc_initgr_data, gids);
|
|
|
6cf099 |
- uint8_t *max_addr;
|
|
|
6cf099 |
+ size_t data_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
ret = sss_nss_mc_get_ctx("initgroups", &initgr_mc_ctx);
|
|
|
6cf099 |
if (ret) {
|
|
|
6cf099 |
return ret;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- /* Get max address of data table. */
|
|
|
6cf099 |
- max_addr = initgr_mc_ctx.data_table + initgr_mc_ctx.dt_size;
|
|
|
6cf099 |
+ /* Get max size of data table. */
|
|
|
6cf099 |
+ data_size = initgr_mc_ctx.dt_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
/* hashes are calculated including the NULL terminator */
|
|
|
6cf099 |
hash = sss_nss_mc_hash(&initgr_mc_ctx, name, name_len + 1);
|
|
|
6cf099 |
@@ -111,7 +111,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
|
|
|
6cf099 |
/* If slot is not within the bounds of mmaped region and
|
|
|
6cf099 |
* it's value is not MC_INVALID_VAL, then the cache is
|
|
|
6cf099 |
* probbably corrupted. */
|
|
|
6cf099 |
- while (MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
/* free record from previous iteration */
|
|
|
6cf099 |
free(rec);
|
|
|
6cf099 |
rec = NULL;
|
|
|
6cf099 |
@@ -132,14 +132,14 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
|
|
|
6cf099 |
rec_name = (char *)data + data->name;
|
|
|
6cf099 |
/* Integrity check
|
|
|
6cf099 |
* - name_len cannot be longer than all strings or data
|
|
|
6cf099 |
- * - data->name cannot point outside strings
|
|
|
6cf099 |
- * - all data must be within data_table
|
|
|
6cf099 |
- * - name must be within data_table */
|
|
|
6cf099 |
- if (name_len > data->data_len
|
|
|
6cf099 |
- || name_len > data->strs_len
|
|
|
6cf099 |
- || (data->strs + name_len) > (data_offset + data->data_len)
|
|
|
6cf099 |
- || (uint8_t *)data->gids + data->data_len > max_addr
|
|
|
6cf099 |
- || (uint8_t *)rec_name + name_len > max_addr) {
|
|
|
6cf099 |
+ * - all data must be within copy of record
|
|
|
6cf099 |
+ * - size of record must be lower that data table size
|
|
|
6cf099 |
+ * - data->strs cannot point outside strings */
|
|
|
6cf099 |
+ if (name_len > data->strs_len
|
|
|
6cf099 |
+ || data->strs_len > data->data_len
|
|
|
6cf099 |
+ || data->data_len > rec->len
|
|
|
6cf099 |
+ || rec->len > data_size
|
|
|
6cf099 |
+ || (data->strs + name_len) > (data_offset + data->data_len)) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
@@ -151,7 +151,7 @@ errno_t sss_nss_mc_initgroups_dyn(const char *name, size_t name_len,
|
|
|
6cf099 |
slot = sss_nss_mc_next_slot_with_hash(rec, hash);
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- if (!MC_SLOT_WITHIN_BOUNDS(slot, initgr_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
|
|
|
6cf099 |
index 10e43e2af43c5e7f1738e281b3ed260d89f3a004..0da7ad0aeece7d38ca34bb3fde64adc898eaf0ae 100644
|
|
|
6cf099 |
--- a/src/sss_client/nss_mc_passwd.c
|
|
|
6cf099 |
+++ b/src/sss_client/nss_mc_passwd.c
|
|
|
6cf099 |
@@ -105,16 +105,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
|
|
|
6cf099 |
uint32_t hash;
|
|
|
6cf099 |
uint32_t slot;
|
|
|
6cf099 |
int ret;
|
|
|
6cf099 |
- size_t strs_offset;
|
|
|
6cf099 |
- uint8_t *max_addr;
|
|
|
6cf099 |
+ const size_t strs_offset = offsetof(struct sss_mc_pwd_data, strs);
|
|
|
6cf099 |
+ size_t data_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
ret = sss_nss_mc_get_ctx("passwd", &pw_mc_ctx);
|
|
|
6cf099 |
if (ret) {
|
|
|
6cf099 |
return ret;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- /* Get max address of data table. */
|
|
|
6cf099 |
- max_addr = pw_mc_ctx.data_table + pw_mc_ctx.dt_size;
|
|
|
6cf099 |
+ /* Get max size of data table. */
|
|
|
6cf099 |
+ data_size = pw_mc_ctx.dt_size;
|
|
|
6cf099 |
|
|
|
6cf099 |
/* hashes are calculated including the NULL terminator */
|
|
|
6cf099 |
hash = sss_nss_mc_hash(&pw_mc_ctx, name, name_len + 1);
|
|
|
6cf099 |
@@ -123,7 +123,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
|
|
|
6cf099 |
/* If slot is not within the bounds of mmaped region and
|
|
|
6cf099 |
* it's value is not MC_INVALID_VAL, then the cache is
|
|
|
6cf099 |
* probbably corrupted. */
|
|
|
6cf099 |
- while (MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ while (MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
/* free record from previous iteration */
|
|
|
6cf099 |
free(rec);
|
|
|
6cf099 |
rec = NULL;
|
|
|
6cf099 |
@@ -140,16 +140,16 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
|
|
|
6cf099 |
continue;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- strs_offset = offsetof(struct sss_mc_pwd_data, strs);
|
|
|
6cf099 |
-
|
|
|
6cf099 |
data = (struct sss_mc_pwd_data *)rec->data;
|
|
|
6cf099 |
/* Integrity check
|
|
|
6cf099 |
* - name_len cannot be longer than all strings
|
|
|
6cf099 |
* - data->name cannot point outside strings
|
|
|
6cf099 |
- * - all strings must be within data_table */
|
|
|
6cf099 |
+ * - all strings must be within copy of record
|
|
|
6cf099 |
+ * - size of record must be lower that data table size */
|
|
|
6cf099 |
if (name_len > data->strs_len
|
|
|
6cf099 |
|| (data->name + name_len) > (strs_offset + data->strs_len)
|
|
|
6cf099 |
- || (uint8_t *)data->strs + data->strs_len > max_addr) {
|
|
|
6cf099 |
+ || data->strs_len > rec->len
|
|
|
6cf099 |
+ || rec->len > data_size) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
@@ -162,7 +162,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
|
|
|
6cf099 |
slot = sss_nss_mc_next_slot_with_hash(rec, hash);
|
|
|
6cf099 |
}
|
|
|
6cf099 |
|
|
|
6cf099 |
- if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
|
|
|
6cf099 |
+ if (!MC_SLOT_WITHIN_BOUNDS(slot, data_size)) {
|
|
|
6cf099 |
ret = ENOENT;
|
|
|
6cf099 |
goto done;
|
|
|
6cf099 |
}
|
|
|
6cf099 |
--
|
|
|
6cf099 |
2.4.3
|
|
|
6cf099 |
|