Blame SOURCES/0041-sss_client-Update-integrity-check-of-records-in-mmap.patch

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