[SERVER-33648] Attempting to perform user- and role-management commands in db.eval() with nolock=false can lead to deadlock Created: 03/Mar/18  Updated: 27/Oct/23  Resolved: 02/Jul/18

Status: Closed
Project: Core Server
Component/s: JavaScript, Security
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Max Hirschhorn Assignee: Backlog - Security Team
Resolution: Gone away Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
depends on SERVER-33662 Remove deprecated db.eval command Closed
Related
related to SERVER-35986 Stop running eval command in parallel... Closed
is related to SERVER-12497 role_management_helpers and user_mana... Closed
is related to SERVER-26101 DBDirectClient isn't safe to auth Closed
is related to SERVER-26257 DBDirectClient should not support auth Closed
is related to SERVER-31552 Authorization User Cache should be ab... Closed
Assigned Teams:
Server Security
Operating System: ALL
Sprint: Platforms 2018-05-07
Participants:
Linked BF Score: 16

 Description   

Attempting to acquire a LockManager lock while holding a mutex is prone to deadlock. The AuthorizationManager::getAuthorizationVersion() function constructs a CacheGuard which acquires the AuthorizationManager::_cacheMutex. While holding the mutex, it calls AuthorizationManager::getStoredAuthorizationVersion(), which attempts to acquire the global lock as part of constructing AutoGetCollectionForReadCommand in AuthzManagerExternalStateMongod::findOne(). Edit: As noted in SERVER-24083, the AuthorizationManager::_cacheMutex is released as part of AuthorizationManager::beginFetchPhase() ; however, a thread must wait if another thread is already calling into AuthorizationManager::getStoredAuthorizationVersion().

A thread running the db.eval() with nolock=false (thus holding the global X lock) would therefore deadlock if it ran any command that constructed a CacheGuard and attempted to acquire the AuthorizationManager::_cacheMutex.

The doc comment for the AuthorizationManager::CacheGuard class describes this general issue; however, it appears we are missing code to enforce it doesn't happen in practice.

NOTE: It is not safe to enter fetch phase while holding a database lock. Fetch phase operations are allowed to acquire database locks themselves, so entering fetch while holding a database lock may lead to deadlock.

https://github.com/mongodb/mongo/blob/r3.7.2/src/mongo/db/auth/authorization_manager.cpp#L167-L169



 Comments   
Comment by Sara Golemon [ 02/Jul/18 ]

Closing this issue as "Gone Away" since db.eval() has been removed from MongoDB.

Generated at Thu Feb 08 04:34:07 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.