summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChenhao Qu <chenhao.qu@mongodb.com>2021-05-24 06:20:39 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-05-24 06:46:40 +0000
commitebc7c43abc561839ca677ea66a690408866ac2f6 (patch)
tree4c53f513b1a0dbea4225c2c9bcd4c09225495862
parent3bee503dad6203dccbcc8d63cb7c04b390f1a2c7 (diff)
downloadmongo-ebc7c43abc561839ca677ea66a690408866ac2f6.tar.gz
Import wiredtiger: 9acb906193234331be4978d07bb3ffe710ece6ed from branch mongodb-5.0
ref: ff7881f921..9acb906193 for: 5.0.1 WT-7135 Additional checks to detect when writing corrupted metadata
-rw-r--r--src/third_party/wiredtiger/import.data2
-rw-r--r--src/third_party/wiredtiger/src/conn/conn_dhandle.c14
-rw-r--r--src/third_party/wiredtiger/src/include/dhandle.h15
-rw-r--r--src/third_party/wiredtiger/src/meta/meta_ckpt.c33
-rw-r--r--src/third_party/wiredtiger/test/suite/test_alter03.py40
5 files changed, 80 insertions, 24 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data
index 41670dd53e8..4485b83d435 100644
--- a/src/third_party/wiredtiger/import.data
+++ b/src/third_party/wiredtiger/import.data
@@ -2,5 +2,5 @@
"vendor": "wiredtiger",
"github": "wiredtiger/wiredtiger.git",
"branch": "mongodb-5.0",
- "commit": "ff7881f9211c93b80162d6f1e61833195329771d"
+ "commit": "9acb906193234331be4978d07bb3ffe710ece6ed"
}
diff --git a/src/third_party/wiredtiger/src/conn/conn_dhandle.c b/src/third_party/wiredtiger/src/conn/conn_dhandle.c
index 210ca733288..5e56a841de4 100644
--- a/src/third_party/wiredtiger/src/conn/conn_dhandle.c
+++ b/src/third_party/wiredtiger/src/conn/conn_dhandle.c
@@ -26,6 +26,9 @@ __conn_dhandle_config_clear(WT_SESSION_IMPL *session)
__wt_free(session, *a);
__wt_free(session, dhandle->cfg);
__wt_free(session, dhandle->meta_base);
+#ifdef HAVE_DIAGNOSTIC
+ __wt_free(session, dhandle->orig_meta_base);
+#endif
}
/*
@@ -85,6 +88,9 @@ __conn_dhandle_config_set(WT_SESSION_IMPL *session)
cfg[3] = NULL;
WT_ERR(__wt_strdup(session, WT_CONFIG_BASE(session, file_meta), &dhandle->cfg[0]));
WT_ASSERT(session, dhandle->meta_base == NULL);
+#ifdef HAVE_DIAGNOSTIC
+ WT_ASSERT(session, dhandle->orig_meta_base == NULL);
+#endif
WT_ERR(__wt_config_collapse(session, cfg, &tmp));
/*
* Now strip out the checkpoint related items from the configuration string and that is now
@@ -108,6 +114,14 @@ __conn_dhandle_config_set(WT_SESSION_IMPL *session)
}
dhandle->cfg[1] = metaconf;
dhandle->meta_base = base;
+ dhandle->meta_base_length = base == NULL ? 0 : strlen(base);
+#ifdef HAVE_DIAGNOSTIC
+ /* Save the original metadata value for further check to avoid writing corrupted data. */
+ if (base == NULL)
+ dhandle->orig_meta_base = NULL;
+ else
+ WT_ERR(__wt_strdup(session, base, &dhandle->orig_meta_base));
+#endif
return (0);
err:
diff --git a/src/third_party/wiredtiger/src/include/dhandle.h b/src/third_party/wiredtiger/src/include/dhandle.h
index 9888c90d33e..01cfeffce6e 100644
--- a/src/third_party/wiredtiger/src/include/dhandle.h
+++ b/src/third_party/wiredtiger/src/include/dhandle.h
@@ -64,12 +64,15 @@ struct __wt_data_handle {
TAILQ_ENTRY(__wt_data_handle) q;
TAILQ_ENTRY(__wt_data_handle) hashq;
- const char *name; /* Object name as a URI */
- uint64_t name_hash; /* Hash of name */
- const char *checkpoint; /* Checkpoint name (or NULL) */
- const char **cfg; /* Configuration information */
- const char *meta_base; /* Base metadata configuration */
-
+ const char *name; /* Object name as a URI */
+ uint64_t name_hash; /* Hash of name */
+ const char *checkpoint; /* Checkpoint name (or NULL) */
+ const char **cfg; /* Configuration information */
+ const char *meta_base; /* Base metadata configuration */
+ size_t meta_base_length; /* Base metadata length */
+#ifdef HAVE_DIAGNOSTIC
+ const char *orig_meta_base; /* Copy of the base metadata configuration */
+#endif
/*
* Sessions holding a connection's data handle will have a non-zero reference count; sessions
* using a connection's data handle will have a non-zero in-use count. Instances of cached
diff --git a/src/third_party/wiredtiger/src/meta/meta_ckpt.c b/src/third_party/wiredtiger/src/meta/meta_ckpt.c
index b5d0ae0b7a1..d4c8f316e5f 100644
--- a/src/third_party/wiredtiger/src/meta/meta_ckpt.c
+++ b/src/third_party/wiredtiger/src/meta/meta_ckpt.c
@@ -193,10 +193,12 @@ __wt_meta_checkpoint_clear(WT_SESSION_IMPL *session, const char *fname)
static int
__ckpt_set(WT_SESSION_IMPL *session, const char *fname, const char *v, bool use_base)
{
+ WT_DATA_HANDLE *dhandle;
WT_DECL_ITEM(tmp);
WT_DECL_RET;
+ size_t meta_base_length;
char *config, *newcfg;
- const char *cfg[3], *str;
+ const char *cfg[3], *meta_base, *str;
/*
* If the caller knows we're on a path like checkpoints where we have a valid checkpoint and
@@ -205,12 +207,35 @@ __ckpt_set(WT_SESSION_IMPL *session, const char *fname, const char *v, bool use_
* use the slower path through configuration parsing functions.
*/
config = newcfg = NULL;
+ dhandle = session->dhandle;
str = v == NULL ? "checkpoint=(),checkpoint_backup_info=(),checkpoint_lsn=" : v;
- if (use_base && session->dhandle != NULL) {
+ if (use_base && dhandle != NULL) {
WT_ERR(__wt_scr_alloc(session, 0, &tmp));
- WT_ASSERT(session, strcmp(session->dhandle->name, fname) == 0);
+ WT_ASSERT(session, strcmp(dhandle->name, fname) == 0);
+
+ /* Check the metadata is not corrupted. */
+ meta_base = dhandle->meta_base;
+ meta_base_length = strlen(meta_base);
+ if (dhandle->meta_base_length != meta_base_length)
+ WT_ERR_PANIC(session, WT_PANIC,
+ "Corrupted metadata. The original metadata length was %lu while the new one is %lu.",
+ dhandle->meta_base_length, meta_base_length);
+#ifdef HAVE_DIAGNOSTIC
+ if (!WT_STREQ(dhandle->orig_meta_base, meta_base))
+ WT_ERR_PANIC(session, WT_PANIC,
+ "Corrupted metadata. The original metadata length was %lu while the new one is %lu. "
+ "The original metadata inserted was %s and the current "
+ "metadata is now %s.",
+ dhandle->meta_base_length, meta_base_length, dhandle->orig_meta_base, meta_base);
+#endif
+
/* Concatenate the metadata base string with the checkpoint string. */
- WT_ERR(__wt_buf_fmt(session, tmp, "%s,%s", session->dhandle->meta_base, str));
+ WT_ERR(__wt_buf_fmt(session, tmp, "%s,%s", meta_base, str));
+ /*
+ * Check the new metadata length is at least as long as the original metadata string with
+ * the checkpoint base stripped out.
+ */
+ WT_ASSERT(session, tmp->size >= dhandle->meta_base_length);
WT_ERR(__wt_metadata_update(session, fname, tmp->mem));
} else {
/* Retrieve the metadata for this file. */
diff --git a/src/third_party/wiredtiger/test/suite/test_alter03.py b/src/third_party/wiredtiger/test/suite/test_alter03.py
index 2ff8ef3e568..f517721b26f 100644
--- a/src/third_party/wiredtiger/test/suite/test_alter03.py
+++ b/src/third_party/wiredtiger/test/suite/test_alter03.py
@@ -34,21 +34,27 @@ from wtscenario import make_scenarios
class test_alter03(wttest.WiredTigerTestCase):
name = "alter03"
- def verify_metadata(self, table_metastr, file_metastr):
- if table_metastr == '' and file_metastr == '':
- return
+ def verify_metadata(self, table_metastr, lsm_metastr, file_metastr):
c = self.session.open_cursor('metadata:', None, None)
if table_metastr != '':
- # We must find a table type entry for this object and it's value
+ # We must find a table type entry for this object and its value
# should contain the provided table meta string.
c.set_key('table:' + self.name)
self.assertNotEqual(c.search(), wiredtiger.WT_NOTFOUND)
value = c.get_value()
self.assertTrue(value.find(table_metastr) != -1)
+ if lsm_metastr != '':
+ # We must find a lsm type entry for this object and its value
+ # should contain the provided lsm meta string.
+ c.set_key('lsm:' + self.name)
+ self.assertNotEqual(c.search(), wiredtiger.WT_NOTFOUND)
+ value = c.get_value()
+ self.assertTrue(value.find(lsm_metastr) != -1)
+
if file_metastr != '':
- # We must find a file type entry for the object and it's value
+ # We must find a file type entry for the object and its value
# should contain the provided file meta string.
c.set_key('file:' + self.name + '.wt')
self.assertNotEqual(c.search(), wiredtiger.WT_NOTFOUND)
@@ -73,20 +79,20 @@ class test_alter03(wttest.WiredTigerTestCase):
c.close()
# Verify the string in the metadata
- self.verify_metadata(app_meta_orig, app_meta_orig)
+ self.verify_metadata(app_meta_orig, '', app_meta_orig)
# Alter app metadata and verify
self.session.alter(uri, 'app_metadata="meta_data_2",')
- self.verify_metadata('app_metadata="meta_data_2",', 'app_metadata="meta_data_2",')
+ self.verify_metadata('app_metadata="meta_data_2",', '', 'app_metadata="meta_data_2",')
# Alter app metadata, explicitly asking for exclusive access and verify
self.session.alter(uri, 'app_metadata="meta_data_3",exclusive_refreshed=true,')
- self.verify_metadata('app_metadata="meta_data_3",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_3",', '', 'app_metadata="meta_data_3",')
# Alter app metadata without taking exclusive lock and verify that only
# table object gets modified
self.session.alter(uri, 'app_metadata="meta_data_4",exclusive_refreshed=false,')
- self.verify_metadata('app_metadata="meta_data_4",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_4",', '', 'app_metadata="meta_data_3",')
# Open a cursor, insert some data and try to alter with session open.
# We should fail unless we ask not to take an exclusive lock
@@ -96,22 +102,22 @@ class test_alter03(wttest.WiredTigerTestCase):
self.assertRaisesException(wiredtiger.WiredTigerError,
lambda: self.session.alter(uri, 'app_metadata="meta_data_5",'))
- self.verify_metadata('app_metadata="meta_data_4",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_4",', '', 'app_metadata="meta_data_3",')
self.assertRaisesException(wiredtiger.WiredTigerError,
lambda: self.session.alter(uri,
'exclusive_refreshed=true,app_metadata="meta_data_5",'))
- self.verify_metadata('app_metadata="meta_data_4",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_4",', '', 'app_metadata="meta_data_3",')
self.session.alter(uri, 'app_metadata="meta_data_5",exclusive_refreshed=false,')
- self.verify_metadata('app_metadata="meta_data_5",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_5",', '', 'app_metadata="meta_data_3",')
c2.close()
# Close and reopen the connection.
# Confirm we retain the app_metadata as expected after reopen
self.reopen_conn()
- self.verify_metadata('app_metadata="meta_data_5",', 'app_metadata="meta_data_3",')
+ self.verify_metadata('app_metadata="meta_data_5",', '', 'app_metadata="meta_data_3",')
# Alter LSM: A non exclusive alter should not be allowed
def test_alter03_lsm_app_metadata(self):
@@ -121,12 +127,20 @@ class test_alter03(wttest.WiredTigerTestCase):
self.session.create(uri, create_params + app_meta_orig)
+ # Try to alter app metadata without exclusive access and verify
self.assertRaisesWithMessage(wiredtiger.WiredTigerError,
lambda: self.session.alter(uri,
'exclusive_refreshed=false,app_metadata="meta_data_2",'),
'/is applicable only on simple tables/')
+ self.verify_metadata('', 'app_metadata="meta_data_1",', '')
+ # Alter app metadata, explicitly asking for exclusive access and verify
self.session.alter(uri, 'exclusive_refreshed=true,app_metadata="meta_data_2",')
+ self.verify_metadata('', 'app_metadata="meta_data_2",', '')
+
+ # Alter app metadata and verify
+ self.session.alter(uri, 'app_metadata="meta_data_3",')
+ self.verify_metadata('', 'app_metadata="meta_data_3",', '')
if __name__ == '__main__':
wttest.run()