diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2023-04-05 20:21:49 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-04-07 01:17:11 +0000 |
commit | 8f16e96a151a823b4db9a5527d108c7a054b419e (patch) | |
tree | 0b656ac7958485f9d5a3a84fe6b421ab14f9bda7 /src/mongo/rpc | |
parent | 759110fa276dc332c2dec26d71c7246f27ebc391 (diff) | |
download | mongo-8f16e96a151a823b4db9a5527d108c7a054b419e.tar.gz |
SERVER-75562 Enforce client metadata limit of 512 on non-internal clients
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata.cpp | 11 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata.h | 2 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/client_metadata_test.cpp | 25 |
3 files changed, 36 insertions, 2 deletions
diff --git a/src/mongo/rpc/metadata/client_metadata.cpp b/src/mongo/rpc/metadata/client_metadata.cpp index 8bd250551cc..24971fbdadc 100644 --- a/src/mongo/rpc/metadata/client_metadata.cpp +++ b/src/mongo/rpc/metadata/client_metadata.cpp @@ -488,7 +488,7 @@ void ClientMetadata::setFromMetadataForOperation(OperationContext* opCtx, BSONEl state.meta = std::move(inputMetadata); } -void ClientMetadata::setFromMetadata(Client* client, BSONElement& elem) { +void ClientMetadata::setFromMetadata(Client* client, BSONElement& elem, bool isInternalClient) { if (elem.eoo()) { return; } @@ -502,6 +502,15 @@ void ClientMetadata::setFromMetadata(Client* client, BSONElement& elem) { } auto meta = ClientMetadata::readFromMetadata(elem); + + if (!isInternalClient) { + uassert(ErrorCodes::ClientMetadataDocumentTooLarge, + str::stream() << "The client metadata document must be less than or equal to " + << kMaxMongoSMetadataDocumentByteLength << " bytes", + static_cast<uint32_t>(meta->_document.objsize()) <= + kMaxMongoSMetadataDocumentByteLength); + } + if (meta && isMongos()) { // If we had a full ClientMetadata and we're on mongos, attach some additional client data. meta->setMongoSMetadata(getHostNameCachedAndPort(), diff --git a/src/mongo/rpc/metadata/client_metadata.h b/src/mongo/rpc/metadata/client_metadata.h index 309eb5668e0..713fab5f819 100644 --- a/src/mongo/rpc/metadata/client_metadata.h +++ b/src/mongo/rpc/metadata/client_metadata.h @@ -230,7 +230,7 @@ public: * This function is only valid to invoke if you are on the Client's thread. This function takes * the Client lock. */ - static void setFromMetadata(Client* client, BSONElement& elem); + static void setFromMetadata(Client* client, BSONElement& elem, bool isInternalClient); /** * Set the ClientMetadata for the OperationContext by reading it from the given BSONElement. diff --git a/src/mongo/rpc/metadata/client_metadata_test.cpp b/src/mongo/rpc/metadata/client_metadata_test.cpp index d01507ba66a..b50a9a69185 100644 --- a/src/mongo/rpc/metadata/client_metadata_test.cpp +++ b/src/mongo/rpc/metadata/client_metadata_test.cpp @@ -387,4 +387,29 @@ TEST(ClientMetadataTest, TestEooElemAsValueToSetOpCtxMetadata) { ASSERT_FALSE(clientMetaDataPtr); } +TEST(ClientMetadataTest, InternalClientLimit) { + auto svcCtx = ServiceContext::make(); + svcCtx->registerClientObserver(std::make_unique<LockerNoopClientObserver>()); + auto client = svcCtx->makeClient("ClientMetadataTest"); + + std::string tooLargeValue(600, 'x'); + + auto doc = BSON(kMetadataDoc << BSON(kDriver << BSON(kName << "n1" << kVersion << "v1") + << kOperatingSystem << BSON(kType << kUnknown) + << "extra" << tooLargeValue)); + auto el = doc.firstElement(); + + // Succeeds because default limit is 1024 unless mongos (unit tests are not mongos) + ASSERT_OK(ClientMetadata::parse(el).getStatus()); + + // Throws since the document is too large + ASSERT_THROWS_CODE(ClientMetadata::setFromMetadata(client.get(), el, false), + DBException, + ErrorCodes::ClientMetadataDocumentTooLarge); + + + // Succeeds because internal client allows 1024 + ASSERT_DOES_NOT_THROW(ClientMetadata::setFromMetadata(client.get(), el, true)); +} + } // namespace mongo |