diff options
author | ADAM David Alan Martin <adam.martin@10gen.com> | 2017-08-30 16:53:25 -0400 |
---|---|---|
committer | ADAM David Alan Martin <adam.martin@10gen.com> | 2017-08-30 18:10:54 -0400 |
commit | a561f9554d2caea44beb334c9c6e92742981f38d (patch) | |
tree | 42c3dcc1d440f4cb15cb92da6351da65850268f6 | |
parent | cef9cd4d98e15dd3ed2b94939e45578335c7876f (diff) | |
download | mongo-a561f9554d2caea44beb334c9c6e92742981f38d.tar.gz |
SERVER-28343 Session checks on GETMORE operations
Make `getMore` operations enforce that the cursor is correctly associated
with the current session.
-rw-r--r-- | jstests/noPassthrough/logical_session_cursor_checks.js | 47 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 57 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.h | 6 | ||||
-rw-r--r-- | src/mongo/db/cursor_manager.cpp | 7 | ||||
-rw-r--r-- | src/mongo/s/query/cluster_cursor_manager.cpp | 9 | ||||
-rw-r--r-- | src/mongo/s/query/cluster_cursor_manager_test.cpp | 58 |
6 files changed, 154 insertions, 30 deletions
diff --git a/jstests/noPassthrough/logical_session_cursor_checks.js b/jstests/noPassthrough/logical_session_cursor_checks.js new file mode 100644 index 00000000000..d292e587c61 --- /dev/null +++ b/jstests/noPassthrough/logical_session_cursor_checks.js @@ -0,0 +1,47 @@ +(function() { + 'use strict'; + + var conn = MongoRunner.runMongod({auth: "", nojournal: ""}); + var admin = conn.getDB("admin"); + var data = conn.getDB("data_storage"); + + admin.createUser({user: 'admin', pwd: 'admin', roles: jsTest.adminUserRoles}); + admin.auth("admin", "admin"); + data.createUser({user: 'admin', pwd: 'admin', roles: jsTest.basicUserRoles}); + data.createUser({user: 'user0', pwd: 'password', roles: jsTest.basicUserRoles}); + admin.logout(); + + data.auth("user0", "password"); + assert.writeOK(data.test.insert({name: "first", data: 1})); + assert.writeOK(data.test.insert({name: "second", data: 2})); + + // Test that getMore works correctly on the same session. + { + var session1 = conn.startSession(); + var session2 = conn.startSession(); + var res = assert.commandWorked( + session1.getDatabase("data_storage").runCommand({find: "test", batchSize: 0})); + var cursorId = res.cursor.id; + assert.commandWorked(session1.getDatabase("data_storage") + .runCommand({getMore: cursorId, collection: "test"})); + + session2.endSession(); + session1.endSession(); + } + + // Test that getMore correctly gives an error, when using a cursor on a different session. + { + var session1 = conn.startSession(); + var session2 = conn.startSession(); + var res = assert.commandWorked( + session1.getDatabase("data_storage").runCommand({find: "test", batchSize: 0})); + var cursorId = res.cursor.id; + assert.commandFailed(session2.getDatabase("data_storage") + .runCommand({getMore: cursorId, collection: "test"})); + + session2.endSession(); + session1.endSession(); + } + + MongoRunner.stopMongod(conn); +})(); diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index 409d5de9d8f..c5edacc96f7 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -975,3 +975,60 @@ bool AuthorizationSession::isImpersonating() const { } } // namespace mongo + +auto mongo::checkCursorSessionPrivilege(OperationContext* const opCtx, + const boost::optional<LogicalSessionId> cursorSessionId) + -> Status { + if (!AuthorizationSession::exists(opCtx->getClient())) { + return Status::OK(); + } + auto* const authSession = AuthorizationSession::get(opCtx->getClient()); + + auto nobodyIsLoggedIn = [authSession] { + return !authSession->getAuthenticatedUserNames().more(); + }; + + auto authHasImpersonatePrivilege = [authSession] { + return authSession->isAuthorizedForPrivilege( + Privilege(ResourcePattern::forClusterResource(), ActionType::impersonate)); + }; + + auto authIsOn = [authSession] { + return authSession->getAuthorizationManager().isAuthEnabled(); + }; + + auto sessionIdToStringOrNone = + [](const boost::optional<LogicalSessionId>& sessionId) -> std::string { + if (sessionId) { + return str::stream() << *sessionId; + } + return "none"; + }; + + // If the cursor has a session then one of the following must be true: + // 1: context session id must match cursor session id. + // 2: user must be magic special (__system, or background task, etc). + + // We do not check the user's ID against the cursor's notion of a user ID, since higher level + // auth checks will check that for us anyhow. + if (authIsOn() && // If the authorization is not on, then we permit anybody to do anything. + cursorSessionId && // If the cursor is not assigned to a session, it is okay to work with + // it from any session. + cursorSessionId != opCtx->getLogicalSessionId() && // If the cursor's session doesn't match + // the Operation Context's session, then + // we should forbid the operation + !nobodyIsLoggedIn() && // Unless, for some reason a user isn't actually using this + // Operation Context (which implies a background job + !authHasImpersonatePrivilege() // Or if the user has an impersonation privilege, in which + // case, the user gets to sidestep certain checks. + ) { + return Status{ErrorCodes::Unauthorized, + str::stream() << "Cursor session id (" + << sessionIdToStringOrNone(cursorSessionId) + << ") is not the same as the operation context's session id (" + << sessionIdToStringOrNone(opCtx->getLogicalSessionId()) + << ")"}; + } + + return Status::OK(); +} diff --git a/src/mongo/db/auth/authorization_session.h b/src/mongo/db/auth/authorization_session.h index edb838c1959..4bd1ebf1d11 100644 --- a/src/mongo/db/auth/authorization_session.h +++ b/src/mongo/db/auth/authorization_session.h @@ -343,4 +343,10 @@ private: bool _impersonationFlag; }; +// Returns a status encoding whether the current session in the specified `opCtx` has privilege to +// access a cursor in the specified `cursorSessionId` parameter. Returns `Status::OK()`, when the +// session is accessible. Returns a `mongo::Status` with information regarding the nature of +// session inaccessibility when the session is not accessible. +Status checkCursorSessionPrivilege(OperationContext* const opCtx, + const boost::optional<LogicalSessionId> cursorSessionId); } // namespace mongo diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp index e7192105867..a4b5712965f 100644 --- a/src/mongo/db/cursor_manager.cpp +++ b/src/mongo/db/cursor_manager.cpp @@ -512,6 +512,13 @@ StatusWith<ClientCursorPin> CursorManager::pinCursor(OperationContext* opCtx, Cu delete cursor; return error; } + + auto cursorPrivilegeStatus = checkCursorSessionPrivilege(opCtx, cursor->getSessionId()); + + if (!cursorPrivilegeStatus.isOK()) { + return cursorPrivilegeStatus; + } + cursor->_isPinned = true; // We use pinning of a cursor as a proxy for active, user-initiated use of a cursor. Therefor, diff --git a/src/mongo/s/query/cluster_cursor_manager.cpp b/src/mongo/s/query/cluster_cursor_manager.cpp index 8585a6114d6..f5cde547cff 100644 --- a/src/mongo/s/query/cluster_cursor_manager.cpp +++ b/src/mongo/s/query/cluster_cursor_manager.cpp @@ -30,6 +30,7 @@ #include "mongo/platform/basic.h" +#include "mongo/db/auth/authorization_session.h" #include "mongo/s/query/cluster_cursor_manager.h" #include <set> @@ -283,7 +284,13 @@ StatusWith<ClusterCursorManager::PinnedCursor> ClusterCursorManager::checkOutCur return cursorInUseStatus(nss, cursorId); } - // We use pinning of a cursor as a proxy for active, user-initiated use of a cursor. Therefor, + const auto cursorPrivilegeStatus = checkCursorSessionPrivilege(opCtx, cursor->getLsid()); + + if (!cursorPrivilegeStatus.isOK()) { + return cursorPrivilegeStatus; + } + + // We use pinning of a cursor as a proxy for active, user-initiated use of a cursor. Therefore, // we pass down to the logical session cache and vivify the record (updating last use). if (cursor->getLsid()) { LogicalSessionCache::get(opCtx)->vivify(opCtx, cursor->getLsid().get()); diff --git a/src/mongo/s/query/cluster_cursor_manager_test.cpp b/src/mongo/s/query/cluster_cursor_manager_test.cpp index 75695e1deb7..c49434619b9 100644 --- a/src/mongo/s/query/cluster_cursor_manager_test.cpp +++ b/src/mongo/s/query/cluster_cursor_manager_test.cpp @@ -140,7 +140,7 @@ TEST_F(ClusterCursorManagerTest, RegisterCursor) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); auto nextResult = pinnedCursor.getValue().next(); ASSERT_OK(nextResult.getStatus()); @@ -172,7 +172,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorBasic) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(checkedOutCursor.getStatus()); ASSERT_EQ(cursorId, checkedOutCursor.getValue().getCursorId()); auto nextResult = checkedOutCursor.getValue().next(); @@ -200,7 +200,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorMultipleCursors) { ClusterCursorManager::CursorLifetime::Mortal)); } for (int i = 0; i < numCursors; ++i) { - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorIds[i], nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorIds[i], _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); auto nextResult = pinnedCursor.getValue().next(); ASSERT_OK(nextResult.getStatus()); @@ -220,10 +220,10 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorPinned) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_EQ(ErrorCodes::CursorInUse, - getManager()->checkOutCursor(nss, cursorId, nullptr).getStatus()); + getManager()->checkOutCursor(nss, cursorId, _opCtx.get()).getStatus()); } // Test that checking out a killed cursor returns an error with code ErrorCodes::CursorNotFound. @@ -236,7 +236,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorKilled) { ClusterCursorManager::CursorLifetime::Mortal)); ASSERT_OK(getManager()->killCursor(nss, cursorId)); ASSERT_EQ(ErrorCodes::CursorNotFound, - getManager()->checkOutCursor(nss, cursorId, nullptr).getStatus()); + getManager()->checkOutCursor(nss, cursorId, _opCtx.get()).getStatus()); } // Test that checking out an unknown cursor returns an error with code ErrorCodes::CursorNotFound. @@ -270,7 +270,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorWrongCursorId) { ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); ASSERT_EQ(ErrorCodes::CursorNotFound, - getManager()->checkOutCursor(nss, cursorId + 1, nullptr).getStatus()); + getManager()->checkOutCursor(nss, cursorId + 1, _opCtx.get()).getStatus()); } // Test that checking out a cursor updates the 'last active' time associated with the cursor to the @@ -284,7 +284,7 @@ TEST_F(ClusterCursorManagerTest, CheckOutCursorUpdateActiveTime) { ClusterCursorManager::CursorLifetime::Mortal)); Date_t cursorRegistrationTime = getClockSource()->now(); getClockSource()->advance(Milliseconds(1)); - auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(checkedOutCursor.getStatus()); checkedOutCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted); getManager()->killMortalCursorsInactiveSince(cursorRegistrationTime); @@ -303,7 +303,7 @@ TEST_F(ClusterCursorManagerTest, ReturnCursorUpdateActiveTime) { ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); Date_t cursorCheckOutTime = getClockSource()->now(); - auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(checkedOutCursor.getStatus()); getClockSource()->advance(Milliseconds(1)); checkedOutCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted); @@ -320,7 +320,7 @@ TEST_F(ClusterCursorManagerTest, KillCursorBasic) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(getManager()->killCursor(nss, pinnedCursor.getValue().getCursorId())); pinnedCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted); @@ -436,7 +436,7 @@ TEST_F(ClusterCursorManagerTest, ShouldNotKillPinnedCursors) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pin = assertGet(getManager()->checkOutCursor(nss, cursorId, nullptr)); + auto pin = assertGet(getManager()->checkOutCursor(nss, cursorId, _opCtx.get())); getManager()->killMortalCursorsInactiveSince(getClockSource()->now()); ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); @@ -523,7 +523,7 @@ TEST_F(ClusterCursorManagerTest, ReapZombieCursorsSkipPinned) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); ASSERT(!isMockCursorKilled(0)); @@ -577,7 +577,7 @@ TEST_F(ClusterCursorManagerTest, StatsPinCursor) { nss, ClusterCursorManager::CursorType::MultiTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_EQ(1U, getManager()->stats().cursorsPinned); } @@ -640,7 +640,7 @@ TEST_F(ClusterCursorManagerTest, StatsKillPinnedCursor) { nss, ClusterCursorManager::CursorType::MultiTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_EQ(1U, getManager()->stats().cursorsPinned); ASSERT_OK(getManager()->killCursor(nss, cursorId)); ASSERT_EQ(0U, getManager()->stats().cursorsPinned); @@ -654,7 +654,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustShardedCursor) { nss, ClusterCursorManager::CursorType::MultiTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(pinnedCursor.getValue().next().getStatus()); ASSERT_EQ(1U, getManager()->stats().cursorsMultiTarget); @@ -670,7 +670,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustNotShardedCursor) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(pinnedCursor.getValue().next().getStatus()); ASSERT_EQ(1U, getManager()->stats().cursorsSingleTarget); @@ -687,7 +687,7 @@ TEST_F(ClusterCursorManagerTest, StatsExhaustPinnedCursor) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(pinnedCursor.getValue().next().getStatus()); ASSERT_EQ(1U, getManager()->stats().cursorsPinned); @@ -704,7 +704,7 @@ TEST_F(ClusterCursorManagerTest, StatsCheckInWithoutExhaustingPinnedCursor) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(pinnedCursor.getValue().next().getStatus()); ASSERT_EQ(1U, getManager()->stats().cursorsPinned); @@ -791,13 +791,13 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorNotExhausted) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(registeredCursor.getStatus()); ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId()); ASSERT_NE(0, cursorId); registeredCursor.getValue().returnCursor(ClusterCursorManager::CursorState::NotExhausted); ASSERT_EQ(0, registeredCursor.getValue().getCursorId()); - auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto checkedOutCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(checkedOutCursor.getStatus()); } @@ -810,7 +810,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhausted) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(registeredCursor.getStatus()); ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId()); ASSERT_NE(0, cursorId); @@ -821,7 +821,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhausted) { // Cursor should have been destroyed without ever being killed. To be sure that the cursor has // not been marked kill pending but not yet destroyed (i.e. that the cursor is not a zombie), we // reapZombieCursors() and check that the cursor still has not been killed. - ASSERT_NOT_OK(getManager()->checkOutCursor(nss, cursorId, nullptr).getStatus()); + ASSERT_NOT_OK(getManager()->checkOutCursor(nss, cursorId, _opCtx.get()).getStatus()); ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); ASSERT(!isMockCursorKilled(0)); @@ -842,7 +842,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhaustedWithNonExhaust nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto registeredCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(registeredCursor.getStatus()); ASSERT_EQ(cursorId, registeredCursor.getValue().getCursorId()); ASSERT_NE(0, cursorId); @@ -851,7 +851,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorReturnCursorExhaustedWithNonExhaust ASSERT_EQ(0, registeredCursor.getValue().getCursorId()); // Cursor should be kill pending, so it will be killed during reaping. - ASSERT_NOT_OK(getManager()->checkOutCursor(nss, cursorId, nullptr).getStatus()); + ASSERT_NOT_OK(getManager()->checkOutCursor(nss, cursorId, _opCtx.get()).getStatus()); ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); ASSERT(isMockCursorKilled(0)); @@ -866,7 +866,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorMoveAssignmentKill) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); pinnedCursor = ClusterCursorManager::PinnedCursor(); ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); @@ -882,7 +882,7 @@ TEST_F(ClusterCursorManagerTest, PinnedCursorDestructorKill) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); } ASSERT(!isMockCursorKilled(0)); getManager()->reapZombieCursors(nullptr); @@ -901,7 +901,7 @@ TEST_F(ClusterCursorManagerTest, RemotesExhausted) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_FALSE(pinnedCursor.getValue().remotesExhausted()); } @@ -914,7 +914,7 @@ TEST_F(ClusterCursorManagerTest, DoNotReapKilledPinnedCursors) { nss, ClusterCursorManager::CursorType::SingleTarget, ClusterCursorManager::CursorLifetime::Mortal)); - auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, nullptr); + auto pinnedCursor = getManager()->checkOutCursor(nss, cursorId, _opCtx.get()); ASSERT_OK(pinnedCursor.getStatus()); ASSERT_OK(getManager()->killCursor(nss, cursorId)); ASSERT(!isMockCursorKilled(0)); @@ -964,7 +964,7 @@ TEST_F(ClusterCursorManagerTest, CannotCheckoutCursorDuringShutdown) { ASSERT(isMockCursorKilled(0)); ASSERT_EQUALS(ErrorCodes::ShutdownInProgress, - getManager()->checkOutCursor(nss, cursorId, nullptr).getStatus()); + getManager()->checkOutCursor(nss, cursorId, _opCtx.get()).getStatus()); } /** |