diff options
author | Shreyas Kalyan <shreyas.kalyan@mongodb.com> | 2022-05-26 14:44:55 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-06-17 22:40:09 +0000 |
commit | cc2a4dffbaed59cf50a0dec5b23ec124622f1240 (patch) | |
tree | 40c80791810744bcde9173ad3eb36f4c863faa39 /src/mongo/db/ops | |
parent | 4817d3fda9bc9a4594beec01ba2244523d695e87 (diff) | |
download | mongo-cc2a4dffbaed59cf50a0dec5b23ec124622f1240.tar.gz |
SERVER-66662 Block insertion into __safeContent__
Diffstat (limited to 'src/mongo/db/ops')
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.cpp | 58 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_exec.h | 3 |
2 files changed, 55 insertions, 6 deletions
diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index ee703965b72..33d1cd596b8 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -604,11 +604,36 @@ SingleWriteResult makeWriteResultForInsertOrDeleteRetry() { return res; } + +// Returns the flags that determine the type of document validation we want to +// perform. First item in the tuple determines whether to bypass document validation altogether, +// second item determines if _safeContent_ array can be modified in an encrypted collection. +std::tuple<bool, bool> getDocumentValidationFlags(OperationContext* opCtx, + const write_ops::WriteCommandRequestBase& req) { + auto& encryptionInfo = req.getEncryptionInformation(); + const bool fleCrudProcessed = getFleCrudProcessed(opCtx, encryptionInfo); + return std::make_tuple(req.getBypassDocumentValidation(), fleCrudProcessed); +} } // namespace +bool getFleCrudProcessed(OperationContext* opCtx, + const boost::optional<EncryptionInformation>& encryptionInfo) { + if (encryptionInfo && encryptionInfo->getCrudProcessed().value_or(false)) { + uassert(6666201, + "External users cannot have crudProcessed enabled", + AuthorizationSession::get(opCtx->getClient()) + ->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), + ActionType::internal)); + + return true; + } + return false; +} + WriteResult performInserts(OperationContext* opCtx, const write_ops::InsertCommandRequest& wholeOp, OperationSource source) { + // Insert performs its own retries, so we should only be within a WriteUnitOfWork when run in a // transaction. auto txnParticipant = TransactionParticipant::get(opCtx); @@ -643,8 +668,15 @@ WriteResult performInserts(OperationContext* opCtx, uassertStatusOK(userAllowedWriteNS(opCtx, wholeOp.getNamespace())); } - DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler( - opCtx, wholeOp.getWriteCommandRequestBase().getBypassDocumentValidation()); + const auto [disableDocumentValidation, fleCrudProcessed] = + getDocumentValidationFlags(opCtx, wholeOp.getWriteCommandRequestBase()); + + DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler(opCtx, + disableDocumentValidation); + + DisableSafeContentValidationIfTrue safeContentValidationDisabler( + opCtx, disableDocumentValidation, fleCrudProcessed); + LastOpFixer lastOpFixer(opCtx, wholeOp.getNamespace()); WriteResult out; @@ -1003,8 +1035,15 @@ WriteResult performUpdates(OperationContext* opCtx, (txnParticipant && opCtx->inMultiDocumentTransaction())); uassertStatusOK(userAllowedWriteNS(opCtx, ns)); - DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler( - opCtx, wholeOp.getWriteCommandRequestBase().getBypassDocumentValidation()); + const auto [disableDocumentValidation, fleCrudProcessed] = + getDocumentValidationFlags(opCtx, wholeOp.getWriteCommandRequestBase()); + + DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler(opCtx, + disableDocumentValidation); + + DisableSafeContentValidationIfTrue safeContentValidationDisabler( + opCtx, disableDocumentValidation, fleCrudProcessed); + LastOpFixer lastOpFixer(opCtx, ns); bool containsRetry = false; @@ -1231,8 +1270,15 @@ WriteResult performDeletes(OperationContext* opCtx, (txnParticipant && opCtx->inMultiDocumentTransaction())); uassertStatusOK(userAllowedWriteNS(opCtx, ns)); - DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler( - opCtx, wholeOp.getWriteCommandRequestBase().getBypassDocumentValidation()); + const auto [disableDocumentValidation, fleCrudProcessed] = + getDocumentValidationFlags(opCtx, wholeOp.getWriteCommandRequestBase()); + + DisableDocumentSchemaValidationIfTrue docSchemaValidationDisabler(opCtx, + disableDocumentValidation); + + DisableSafeContentValidationIfTrue safeContentValidationDisabler( + opCtx, disableDocumentValidation, fleCrudProcessed); + LastOpFixer lastOpFixer(opCtx, ns); bool containsRetry = false; diff --git a/src/mongo/db/ops/write_ops_exec.h b/src/mongo/db/ops/write_ops_exec.h index 548a3034713..3550a51c1ce 100644 --- a/src/mongo/db/ops/write_ops_exec.h +++ b/src/mongo/db/ops/write_ops_exec.h @@ -64,6 +64,9 @@ struct WriteResult { bool canContinue = true; }; +bool getFleCrudProcessed(OperationContext* opCtx, + const boost::optional<EncryptionInformation>& encryptionInfo); + /** * Performs a batch of inserts, updates, or deletes. * |