Blob Blame History Raw
From 8c3c6a779b9d1b20c7b413caa25381ab07a08a87 Mon Sep 17 00:00:00 2001
From: Ravishankar N <ravishankar@redhat.com>
Date: Wed, 19 Sep 2018 15:20:27 +0530
Subject: [PATCH 378/385] posix/afr: handle backward compatibility for
 rchecksum fop

Patch on upstream master: https://review.gluster.org/#/c/glusterfs/+/19538/

Added a volume option 'fips-mode-rchecksum' tied to op version 4.
If not set, rchecksum fop will use MD5 instead of SHA256.

Change-Id: I720777c0ab36985774e6bb877689fe45b64eb777
BUG: 1459709
Signed-off-by: Ravishankar N <ravishankar@redhat.com>
Reviewed-on: https://code.engineering.redhat.com/gerrit/150479
Tested-by: RHGS Build Bot <nigelb@redhat.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
---
 libglusterfs/src/checksum.c                     |  7 +++++
 libglusterfs/src/checksum.h                     |  2 ++
 libglusterfs/src/globals.h                      |  2 ++
 xlators/cluster/afr/src/afr-self-heal-common.c  |  8 ++++-
 xlators/cluster/afr/src/afr-self-heal-data.c    | 29 +++++++++++++-----
 xlators/cluster/afr/src/afr.h                   |  1 +
 xlators/mgmt/glusterd/src/glusterd-volume-set.c |  6 ++++
 xlators/protocol/server/src/server-common.c     |  2 +-
 xlators/storage/posix/src/posix.c               | 39 +++++++++++++++++++++++--
 xlators/storage/posix/src/posix.h               |  2 ++
 10 files changed, 85 insertions(+), 13 deletions(-)

diff --git a/libglusterfs/src/checksum.c b/libglusterfs/src/checksum.c
index a7f9877..561ca04 100644
--- a/libglusterfs/src/checksum.c
+++ b/libglusterfs/src/checksum.c
@@ -8,6 +8,7 @@
   cases as published by the Free Software Foundation.
 */
 
+#include <openssl/md5.h>
 #include <openssl/sha.h>
 #include <zlib.h>
 #include <stdint.h>
@@ -36,3 +37,9 @@ gf_rsync_strong_checksum (unsigned char *data, size_t len,
 {
         SHA256((const unsigned char *)data, len, sha256_md);
 }
+
+void
+gf_rsync_md5_checksum (unsigned char *data, size_t len, unsigned char *md5)
+{
+        MD5 (data, len, md5);
+}
diff --git a/libglusterfs/src/checksum.h b/libglusterfs/src/checksum.h
index bf7eeed..677a59a 100644
--- a/libglusterfs/src/checksum.h
+++ b/libglusterfs/src/checksum.h
@@ -17,4 +17,6 @@ gf_rsync_weak_checksum (unsigned char *buf, size_t len);
 void
 gf_rsync_strong_checksum (unsigned char *buf, size_t len, unsigned char *sum);
 
+void
+gf_rsync_md5_checksum (unsigned char *data, size_t len, unsigned char *md5);
 #endif /* __CHECKSUM_H__ */
diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h
index 39d9716..e810ea7 100644
--- a/libglusterfs/src/globals.h
+++ b/libglusterfs/src/globals.h
@@ -109,6 +109,8 @@
 
 #define GD_OP_VERSION_3_13_2   31302 /* Op-version for GlusterFS 3.13.2 */
 
+#define GD_OP_VERSION_4_0_0 40000 /* Op-version for GlusterFS 4.0.0 */
+
 /* Downstream only change */
 #define GD_OP_VERSION_3_11_2   31102 /* Op-version for RHGS 3.3.1-async */
 
diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c
index 2989b9e..7e6a691 100644
--- a/xlators/cluster/afr/src/afr-self-heal-common.c
+++ b/xlators/cluster/afr/src/afr-self-heal-common.c
@@ -665,7 +665,13 @@ afr_reply_copy (struct afr_reply *dst, struct afr_reply *src)
 	if (dst->xdata)
 		dict_unref (dst->xdata);
 	dst->xdata = xdata;
-	memcpy (dst->checksum, src->checksum, SHA256_DIGEST_LENGTH);
+        if (xdata && dict_get_str_boolean (xdata, "fips-mode-rchecksum",
+            _gf_false) == _gf_true) {
+                memcpy (dst->checksum, src->checksum, SHA256_DIGEST_LENGTH);
+        } else {
+                memcpy (dst->checksum, src->checksum, MD5_DIGEST_LENGTH);
+        }
+        dst->fips_mode_rchecksum = src->fips_mode_rchecksum;
 }
 
 void
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c
index dd44deb..556a8f9 100644
--- a/xlators/cluster/afr/src/afr-self-heal-data.c
+++ b/xlators/cluster/afr/src/afr-self-heal-data.c
@@ -38,11 +38,21 @@ __checksum_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
 	replies[i].valid = 1;
 	replies[i].op_ret = op_ret;
 	replies[i].op_errno = op_errno;
-        if (xdata)
+        if (xdata) {
                 replies[i].buf_has_zeroes = dict_get_str_boolean (xdata,
                                                    "buf-has-zeroes", _gf_false);
-	if (strong)
-            memcpy (local->replies[i].checksum, strong, SHA256_DIGEST_LENGTH);
+                replies[i].fips_mode_rchecksum = dict_get_str_boolean (xdata,
+                                              "fips-mode-rchecksum", _gf_false);
+        }
+	if (strong) {
+                if (replies[i].fips_mode_rchecksum) {
+                        memcpy (local->replies[i].checksum, strong,
+                                SHA256_DIGEST_LENGTH);
+                } else {
+                        memcpy (local->replies[i].checksum, strong,
+                                MD5_DIGEST_LENGTH);
+                }
+        }
 
 	syncbarrier_wake (&local->barrier);
 	return 0;
@@ -58,11 +68,13 @@ __afr_can_skip_data_block_heal (call_frame_t *frame, xlator_t *this, fd_t *fd,
 	afr_local_t *local = NULL;
 	unsigned char *wind_subvols = NULL;
         gf_boolean_t checksum_match = _gf_true;
+        struct afr_reply *replies = NULL;
         dict_t *xdata = NULL;
 	int i = 0;
 
 	priv = this->private;
 	local = frame->local;
+        replies = local->replies;
 
         xdata = dict_new();
         if (!xdata)
@@ -83,16 +95,17 @@ __afr_can_skip_data_block_heal (call_frame_t *frame, xlator_t *this, fd_t *fd,
         if (xdata)
                 dict_unref (xdata);
 
-	if (!local->replies[source].valid || local->replies[source].op_ret != 0)
+	if (!replies[source].valid || replies[source].op_ret != 0)
 		return _gf_false;
 
 	for (i = 0; i < priv->child_count; i++) {
 		if (i == source)
 			continue;
-                if (local->replies[i].valid) {
-                        if (memcmp (local->replies[source].checksum,
-                                    local->replies[i].checksum,
-                                    SHA256_DIGEST_LENGTH)) {
+                if (replies[i].valid) {
+                        if (memcmp (replies[source].checksum,
+                                    replies[i].checksum,
+                                    replies[source].fips_mode_rchecksum ?
+                                    SHA256_DIGEST_LENGTH : MD5_DIGEST_LENGTH)) {
                                 checksum_match = _gf_false;
                                 break;
                         }
diff --git a/xlators/cluster/afr/src/afr.h b/xlators/cluster/afr/src/afr.h
index 7cb6f00..76ad292 100644
--- a/xlators/cluster/afr/src/afr.h
+++ b/xlators/cluster/afr/src/afr.h
@@ -273,6 +273,7 @@ struct afr_reply {
         /* For rchecksum */
 	uint8_t checksum[SHA256_DIGEST_LENGTH];
         gf_boolean_t buf_has_zeroes;
+        gf_boolean_t fips_mode_rchecksum;
         /* For lookup */
         int8_t need_heal;
 };
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
index 474587a..0ff512d 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
@@ -2868,6 +2868,12 @@ struct volopt_map_entry glusterd_volopt_map[] = {
           .voltype     = "storage/posix",
           .op_version  = GD_OP_VERSION_3_13_0,
         },
+        { .option      = "fips-mode-rchecksum",
+          .key         = "storage.fips-mode-rchecksum",
+          .type        = NO_DOC,
+          .voltype     = "storage/posix",
+          .op_version  = GD_OP_VERSION_4_0_0,
+        },
         { .key         = "storage.bd-aio",
           .voltype     = "storage/bd",
           .op_version  = GD_OP_VERSION_RHS_3_0
diff --git a/xlators/protocol/server/src/server-common.c b/xlators/protocol/server/src/server-common.c
index 9c38706..ce33089 100644
--- a/xlators/protocol/server/src/server-common.c
+++ b/xlators/protocol/server/src/server-common.c
@@ -298,7 +298,7 @@ server_post_rchecksum (gfs3_rchecksum_rsp *rsp, uint32_t weak_checksum,
         rsp->weak_checksum = weak_checksum;
 
         rsp->strong_checksum.strong_checksum_val = (char *)strong_checksum;
-        rsp->strong_checksum.strong_checksum_len = SHA256_DIGEST_LENGTH;
+        rsp->strong_checksum.strong_checksum_len = MD5_DIGEST_LENGTH;
 
 }
 
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index 4e13465..1d3f1ee 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -7000,7 +7000,9 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this,
         ssize_t                 bytes_read      = 0;
         int32_t                 weak_checksum   = 0;
         int32_t                 zerofillcheck   = 0;
+        unsigned char           md5_checksum[MD5_DIGEST_LENGTH] = {0};
         unsigned char           strong_checksum[SHA256_DIGEST_LENGTH] = {0};
+        unsigned char           *checksum = NULL;
         struct posix_private    *priv           = NULL;
         dict_t                  *rsp_xdata      = NULL;
         gf_boolean_t            buf_has_zeroes  = _gf_false;
@@ -7069,13 +7071,31 @@ posix_rchecksum (call_frame_t *frame, xlator_t *this,
                 }
         }
         weak_checksum = gf_rsync_weak_checksum ((unsigned char *) buf, (size_t) ret);
-        gf_rsync_strong_checksum ((unsigned char *) buf, (size_t) bytes_read,
-                                  (unsigned char *) strong_checksum);
 
+        if (priv->fips_mode_rchecksum) {
+                ret = dict_set_int32 (rsp_xdata, "fips-mode-rchecksum", 1);
+                if (ret) {
+                        gf_msg (this->name, GF_LOG_WARNING, -ret,
+                                P_MSG_DICT_SET_FAILED, "%s: Failed to set "
+                                "dictionary value for key: %s",
+                                uuid_utoa (fd->inode->gfid),
+                                "fips-mode-rchecksum");
+                        goto out;
+                }
+                checksum = strong_checksum;
+                gf_rsync_strong_checksum ((unsigned char *)buf,
+                                          (size_t) bytes_read,
+                                          (unsigned char *)checksum);
+        } else {
+                checksum = md5_checksum;
+                gf_rsync_md5_checksum ((unsigned char *)buf,
+                                       (size_t) bytes_read,
+                                       (unsigned char *)checksum);
+        }
         op_ret = 0;
 out:
         STACK_UNWIND_STRICT (rchecksum, frame, op_ret, op_errno,
-                             weak_checksum, strong_checksum, rsp_xdata);
+                             weak_checksum, checksum, rsp_xdata);
         if (rsp_xdata)
                 dict_unref (rsp_xdata);
         GF_FREE (alloc_buf);
@@ -7295,6 +7315,9 @@ reconfigure (xlator_t *this, dict_t *options)
         GF_OPTION_RECONF ("shared-brick-count", priv->shared_brick_count,
                           options, int32, out);
 
+        GF_OPTION_RECONF ("fips-mode-rchecksum", priv->fips_mode_rchecksum,
+                          options, bool, out);
+
 	ret = 0;
 out:
 	return ret;
@@ -7953,6 +7976,9 @@ init (xlator_t *this)
 
         GF_OPTION_INIT ("batch-fsync-delay-usec", _private->batch_fsync_delay_usec,
                         uint32, out);
+
+        GF_OPTION_INIT ("fips-mode-rchecksum", _private->fips_mode_rchecksum,
+                        bool, out);
 out:
         return ret;
 }
@@ -8182,5 +8208,12 @@ struct volume_options options[] = {
           " Useful for displaying the proper usable size through statvfs() "
           "call (df command)",
         },
+        {
+          .key = {"fips-mode-rchecksum"},
+          .type = GF_OPTION_TYPE_BOOL,
+          .default_value = "off",
+          .description = "If enabled, posix_rchecksum uses the FIPS compliant"
+                         "SHA256 checksum. MD5 otherwise."
+        },
         { .key  = {NULL} }
 };
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
index eaf4d0d..bda4172 100644
--- a/xlators/storage/posix/src/posix.h
+++ b/xlators/storage/posix/src/posix.h
@@ -227,6 +227,8 @@ struct posix_private {
         /* Option to handle the cases of multiple bricks exported from
            same backend. Very much usable in brick-splitting feature. */
         int32_t shared_brick_count;
+
+        gf_boolean_t fips_mode_rchecksum;
 };
 
 typedef struct {
-- 
1.8.3.1