diff options
author | Tess Avitabile <tess.avitabile@mongodb.com> | 2020-09-02 20:25:08 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-27 13:16:01 +0000 |
commit | 100c645fe1655c03c9fcb478f402a973e5c39278 (patch) | |
tree | 2d6f75d2136618caab3505f6ed5a3e754bce1652 | |
parent | e4943822d3593552b223d8754676949ce8952eaa (diff) | |
download | mongo-100c645fe1655c03c9fcb478f402a973e5c39278.tar.gz |
SERVER-50116 Forbid oplog writes when replication is enabled
(cherry picked from commit 7b2913a64bc8812a9ab71ce27fe14bb2f517376f)
(cherry picked from commit 73dd69d37bc64c58a800c8d1225e35d3ca6241cb)
(cherry picked from commit eb7e3fb83f19ad86074b052ff8956d5e39ffabcb)
6 files changed, 61 insertions, 5 deletions
diff --git a/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js b/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js new file mode 100644 index 00000000000..bb2af0f0ee7 --- /dev/null +++ b/jstests/noPassthrough/oplog_writes_only_permitted_on_standalone.js @@ -0,0 +1,43 @@ +/** + * Tests that oplog writes are forbidden on replica set members. In standalone mode, it is permitted + * to insert oplog entries. + * @tags: [ + * requires_persistence, + * requires_replication, + * ] + */ +(function() { + "use strict"; + + const rst = new ReplSetTest({nodes: 1}); + rst.startSet(); + rst.initiate(); + + let conn = rst.getPrimary(); + assert.writeOK(conn.getDB("test").coll.insert({_id: 0, a: 0})); + + let oplog = conn.getDB("local").oplog.rs; + + // Construct a valid oplog entry. + const lastOplogEntry = oplog.find().sort({ts: -1}).limit(1).toArray()[0]; + const highestTS = lastOplogEntry.ts; + const toInsert = Object.extend(lastOplogEntry, { + op: "u", + ns: "test.coll", + o: {$set: {a: 1}}, + o2: {_id: 0}, + ts: Timestamp(highestTS.getTime(), highestTS.getInc() + 1) + }); + + jsTestLog("Test that oplog writes are banned when replication is enabled."); + assert.writeErrorWithCode(oplog.insert(toInsert), ErrorCodes.InvalidNamespace); + + jsTestLog("Restart the node in standalone mode."); + rst.stop(0, undefined /*signal*/, undefined /*opts*/, {forRestart: true}); + conn = rst.start(0, {noReplSet: true, noCleanData: true}); + + jsTestLog("Test that oplog writes are permitted in standalone mode."); + assert.writeOK(conn.getDB("local").oplog.rs.insert(toInsert)); + + rst.stopSet(); +}()); diff --git a/jstests/replsets/oplog_truncated_on_recovery.js b/jstests/replsets/oplog_truncated_on_recovery.js index cca4051b369..50bb399f6a1 100644 --- a/jstests/replsets/oplog_truncated_on_recovery.js +++ b/jstests/replsets/oplog_truncated_on_recovery.js @@ -72,7 +72,9 @@ {upsert: true, writeConcern: {w: 1}}))); // Insert a diverged oplog entry that will be truncated after restart. - log(assert.writeOK(localDB.oplog.rs.insert({ + replTest.stop(0); + master = replTest.start(0, {noReplSet: true, noCleanData: true}); + log(assert.writeOK(master.getDB("local").oplog.rs.insert({ _id: ObjectId(), ns: "", ts: divergedTS, @@ -81,8 +83,7 @@ t: NumberLong(-1), o: {} }))); - log(localDB.oplog.rs.find().toArray()); - log(assert.commandWorked(localDB.adminCommand("replSetGetStatus"))); + log(master.getDB("local").oplog.rs.find().toArray()); log("restart primary"); replTest.restart(master); replTest.waitForState(master, ReplSetTest.State.RECOVERING); diff --git a/jstests/replsets/rollback_cmd_unrollbackable.js b/jstests/replsets/rollback_cmd_unrollbackable.js index 33a6f686929..d1f4af4cf02 100644 --- a/jstests/replsets/rollback_cmd_unrollbackable.js +++ b/jstests/replsets/rollback_cmd_unrollbackable.js @@ -47,6 +47,8 @@ options = { }; // Inserts another oplog entry to set minValid ahead. assert.writeOK(b_conn.getDB(name).foo.insert({x: 123})); +replTest.stop(BID); +b_conn = replTest.start(BID, {noReplSet: true, noCleanData: true}); var oplog_entry = b_conn.getDB("local").oplog.rs.find().sort({$natural: -1})[0]; oplog_entry["ts"] = Timestamp(oplog_entry["ts"].t, oplog_entry["ts"].i + 1); oplog_entry["op"] = "c"; diff --git a/jstests/replsets/rollback_different_h.js b/jstests/replsets/rollback_different_h.js index 0c4967aa691..b584f521964 100644 --- a/jstests/replsets/rollback_different_h.js +++ b/jstests/replsets/rollback_different_h.js @@ -49,8 +49,8 @@ assert.writeOK(a_conn.getDB(name).foo.insert({x: 1}, options)); replTest.stop(AID); // change the h value of the most recent entry on B -master = replTest.getPrimary(); -assert(b_conn.host === master.host, "b_conn assumed to be master"); +replTest.stop(1, undefined /*signal*/, undefined /*opts*/, {forRestart: true}); +b_conn = replTest.start(1, {noReplSet: true, noCleanData: true}); options = { writeConcern: {w: 1, wtimeout: ReplSetTest.kDefaultTimeoutMS}, upsert: true @@ -60,8 +60,12 @@ oplog_entry["ts"].t++; oplog_entry["h"] = NumberLong(1); res = b_conn.getDB("local").oplog.rs.insert(oplog_entry); assert(res.nInserted > 0, tojson(res)); +replTest.stop(1, undefined /*signal*/, undefined /*opts*/, {forRestart: true}); +b_conn = replTest.start(1, {noCleanData: true}); // another insert to set minvalid ahead +master = replTest.getPrimary(); +assert(b_conn.host === master.host, "b_conn assumed to be master"); assert.writeOK(b_conn.getDB(name).foo.insert({x: 123})); // shut down B and bring back the original master diff --git a/jstests/replsets/rollback_refetch_no_uuid/rollback_cmd_unrollbackable.js b/jstests/replsets/rollback_refetch_no_uuid/rollback_cmd_unrollbackable.js index f544520e686..43d51e7d574 100644 --- a/jstests/replsets/rollback_refetch_no_uuid/rollback_cmd_unrollbackable.js +++ b/jstests/replsets/rollback_refetch_no_uuid/rollback_cmd_unrollbackable.js @@ -47,6 +47,8 @@ options = { }; // Inserts another oplog entry to set minValid ahead. assert.writeOK(b_conn.getDB(name).foo.insert({x: 123})); +replTest.stop(BID); +b_conn = replTest.start(BID, {noReplSet: true, noCleanData: true}); var oplog_entry = b_conn.getDB("local").oplog.rs.find().sort({$natural: -1})[0]; oplog_entry["ts"] = Timestamp(oplog_entry["ts"].t, oplog_entry["ts"].i + 1); oplog_entry["op"] = "c"; diff --git a/src/mongo/db/ops/insert.cpp b/src/mongo/db/ops/insert.cpp index ef49668a8d1..a4985726090 100644 --- a/src/mongo/db/ops/insert.cpp +++ b/src/mongo/db/ops/insert.cpp @@ -38,6 +38,7 @@ #include "mongo/bson/bson_depth.h" #include "mongo/db/logical_clock.h" #include "mongo/db/logical_time.h" +#include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/views/durable_view_catalog.h" #include "mongo/util/mongoutils/str.h" @@ -190,6 +191,9 @@ Status userAllowedWriteNS(StringData db, StringData coll) { if (coll == "system.profile") { return Status(ErrorCodes::InvalidNamespace, str::stream() << "cannot write to '" << db << ".system.profile'"); + } else if (db == "local" && coll == "oplog.rs" && + repl::ReplicationCoordinator::get(getGlobalServiceContext())->isReplEnabled()) { + return Status(ErrorCodes::InvalidNamespace, "cannot write to 'local.oplog.rs'"); } return userAllowedCreateNS(db, coll); } |