Fixed issues with concurrent access to User object

ContextAccess might be updated from another thread, nullifying UserPtr.
Can happen if user was dropped in concurrent query.

This could crash server under certain conditions.
This commit is contained in:
Vasily Nemkov 2022-05-05 13:17:13 +03:00
parent 643fff9cba
commit 58953b5f28
4 changed files with 11 additions and 3 deletions

View File

@ -117,7 +117,7 @@ namespace
void checkGranteeIsAllowed(const ContextAccess & current_user_access, const UUID & grantee_id, const IAccessEntity & grantee)
{
auto current_user = current_user_access.getUser();
if (current_user && !current_user->grantees.match(grantee_id))
if (!current_user || !current_user->grantees.match(grantee_id))
throw Exception(grantee.formatTypeWithName() + " is not allowed as grantee", ErrorCodes::ACCESS_DENIED);
}

View File

@ -48,7 +48,7 @@ void InterpreterSetRoleQuery::setRole(const ASTSetRoleQuery & query)
{
for (const auto & id : roles_from_query.getMatchingIDs())
{
if (!user->granted_roles.isGranted(id))
if (!user || !user->granted_roles.isGranted(id))
throw Exception("Role should be granted to set current", ErrorCodes::SET_NON_GRANTED_ROLE);
new_current_roles.emplace_back(id);
}

View File

@ -128,6 +128,7 @@ namespace ErrorCodes
extern const int LOGICAL_ERROR;
extern const int INVALID_SETTING_VALUE;
extern const int UNKNOWN_READ_METHOD;
extern const int UNKNOWN_USER;
}
@ -719,6 +720,9 @@ void Context::setUser(const UUID & user_id_)
user_id_, /* current_roles = */ {}, /* use_default_roles = */ true, settings, current_database, client_info);
auto user = access->getUser();
if (!user)
throw Exception(ErrorCodes::UNKNOWN_USER, "User has been dropped");
current_roles = std::make_shared<std::vector<UUID>>(user->granted_roles.findGranted(user->default_roles));
auto default_profile_info = access->getDefaultProfileInfo();
@ -765,6 +769,9 @@ void Context::setCurrentRoles(const std::vector<UUID> & current_roles_)
void Context::setCurrentRolesDefault()
{
auto user = getUser();
if (!user)
throw Exception(ErrorCodes::UNKNOWN_USER, "User has been dropped");
setCurrentRoles(user->granted_roles.findGranted(user->default_roles));
}

View File

@ -438,11 +438,12 @@ ContextMutablePtr Session::makeQueryContextImpl(const ClientInfo * client_info_t
ContextMutablePtr query_context = Context::createCopy(from_session_context ? session_context : global_context);
query_context->makeQueryContext();
auto query_context_user = query_context->getUser();
LOG_DEBUG(log, "{} Creating query context from {} context, user_id: {}, parent context user: {}",
toString(auth_id),
from_session_context ? "session" : "global",
user_id ? toString(*user_id) : "<EMPTY>",
query_context->getUser() ? query_context->getUser()->getName() : "<NOT SET>");
query_context_user ? query_context_user->getName() : "<NOT SET>");
/// Copy the specified client info to the new query context.
auto & res_client_info = query_context->getClientInfo();