Make objects used in service_impl.cpp (mostly) thread safe 15/319215/1
authorTomasz Swierczek <t.swierczek@samsung.com>
Thu, 17 Oct 2024 09:05:14 +0000 (11:05 +0200)
committerTomasz Swierczek <t.swierczek@samsung.com>
Thu, 17 Oct 2024 13:33:27 +0000 (15:33 +0200)
So that its easier to introduce multiple-threads into the daemon.

**Disclaimer**
--------------
(1)
privilege_db is thread safe as long as only one thread is managing RW transactions
on the DB (each API of the DB takes & releases internal mutex).

This is enough to introduce a new separate thread just for prepare_app2 functionality
that only READS data and 2nd thread (current worker) operating on everything else,
including the RW operations.

To make a thread pool operate on many RW requests, transactions would need to be
handled in different way, so that they do not intertwine & the process
makes just one transaction at a time on the shared connection to the DB.

(2)
NSMountLogic is used only on policy update, so will be used only from the
standard worker thread (not the prepare_app2 thread). If thread pool will have
to be implemented in security-manager (or more than 1 thread to handle updates),
this would have to get reviewed.

(3)
Updates of permissible file with Smack labels of apps were left untouched to be done
on one thread (worker thread).

Change-Id: Idb228c52104058dce0c2ce43322613de09b8a06f

src/common/cynara.cpp
src/common/include/cynara.h
src/common/include/privilege_db.h
src/common/include/service_impl.h
src/common/privilege_db.cpp

index 42dec87e6b8d26b0cd375a0f73732b13c86c9c7a..b712179fdac06b071f611a5c6c7f2e42cb62762a 100644 (file)
@@ -317,6 +317,7 @@ CynaraAdmin::~CynaraAdmin()
 
 void CynaraAdmin::setPolicies(const std::vector<CynaraAdminPolicy> &policies)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     if (policies.empty()) {
         LogDebug("no policies to set in Cynara.");
         return;
@@ -693,6 +694,7 @@ void CynaraAdmin::listPolicies(
     const std::string &privilege,
     std::vector<CynaraAdminPolicy> &policies)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     struct cynara_admin_policy ** pp_policies = nullptr;
 
     checkCynaraError(
@@ -713,6 +715,7 @@ void CynaraAdmin::listPolicies(
 void CynaraAdmin::emptyBucket(const std::string &bucketName, bool recursive, const std::string &client,
     const std::string &user, const std::string &privilege)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     checkCynaraError(
         cynara_admin_erase(m_cynaraAdmin, bucketName.c_str(), static_cast<int>(recursive),
             client.c_str(), user.c_str(), privilege.c_str()),
@@ -722,6 +725,7 @@ void CynaraAdmin::emptyBucket(const std::string &bucketName, bool recursive, con
 
 void CynaraAdmin::fetchCynaraPolicyDescriptions(bool forceRefresh)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     struct cynara_admin_policy_descr **descriptions = nullptr;
 
     if (!forceRefresh && m_policyDescriptionsInitialized)
@@ -848,6 +852,7 @@ int CynaraAdmin::convertToPolicyType(const std::string &policy, bool forceRefres
 void CynaraAdmin::check(const std::string &label, const std::string &user, const std::string &privilege,
     const std::string &bucket, int &result, std::string &resultExtra, const bool recursive)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     char *resultExtraCstr = nullptr;
 
     checkCynaraError(
@@ -869,7 +874,9 @@ void CynaraAdmin::check(const std::string &label, const std::string &user, const
     }
 }
 
-std::vector<CynaraAdmin::BatchCheckResult> CynaraAdmin::checkBatch(const std::vector<BatchCheck>& checks) {
+std::vector<CynaraAdmin::BatchCheckResult> CynaraAdmin::checkBatch(const std::vector<BatchCheck>& checks)
+{
+    std::lock_guard<std::mutex> lock(m_api_mutex);
     std::vector<cynara_admin_batch_check> raw_checks;
     raw_checks.reserve(checks.size());
     for (const auto& check : checks) {
@@ -1056,6 +1063,9 @@ void Cynara::run()
 bool Cynara::check(const std::string &label, const std::string &privilege,
         const std::string &user, const std::string &session)
 {
+    std::lock_guard<std::mutex> lock(m_api_mutex);
+    // TODO remove the async API here in refactoring later
+    // introduced in 2015 with multithreaded security-manager in mind
     LogDebug("check: client = " << label << ", user = " << user <<
         ", privilege = " << privilege << ", session = " << session);
 
index f3d3a19bd42e6a85d09bdc419b099a91364206bf..cb4e1961a8ba73e8942872557a4cd3ffc6bf8956 100644 (file)
@@ -390,6 +390,7 @@ private:
     static TypeToDescriptionMap s_typeToDescription;
     static DescriptionToTypeMap s_descriptionToType;
 
+    std::mutex m_api_mutex;
     struct cynara_admin *m_cynaraAdmin;
     bool m_policyDescriptionsInitialized;
 };
@@ -430,6 +431,7 @@ private:
 
     cynara_async *m_cynara;
     std::mutex m_mutex;
+    std::mutex m_api_mutex;
     std::thread m_thread;
 
     const int m_eventFd;
index 8d204464ff4d2fce17f7665b457f0a4426264906..39b9d3d4517fb20566e1b388014efe45c33a6f81 100644 (file)
@@ -36,6 +36,7 @@
 #include <list>
 #include <utility>
 #include <map>
+#include <mutex>
 #include <stdbool.h>
 #include <string>
 #include <vector>
@@ -100,6 +101,7 @@ class PrivilegeDb {
      */
 
 private:
+    std::mutex m_api_mutex;
     /**
      * Wrapper for prepared statement, it will reset statement at destruction.
      */
index 687f3cbbfdbc23924d902b3169ae3961d448b31f..2f70328a75f2dc2c8cb6ad78b43655d9103ccf96 100644 (file)
@@ -474,12 +474,14 @@ private:
 
     int getAppDefinedPrivilegeDescription(uid_t uid, const std::string &privilege, std::string &appName, std::string &pkgName, std::string &license);
 
-    Cynara m_cynara;
-    SmackRules m_smackRules;
-    PrivilegeDb m_privilegeDb;
-    CynaraAdmin m_cynaraAdmin;
-    PrivilegeGids m_privilegeGids;
-    NSMountLogic m_NSMountLogic;
+    // Objects below have to be accessed under a mutex each time - need to be thread safe at usage
+    Cynara m_cynara;            // added api mutex
+    SmackRules m_smackRules;    // seems to work out of the box, assuming that libsmack can be used from many threads at once
+    PrivilegeDb m_privilegeDb;  // added api mutex -> if one thread only does RW ScopedTransactions (from service_impl), its okay
+    CynaraAdmin m_cynaraAdmin;  // added api mutex
+    PrivilegeGids m_privilegeGids;  // seems to work out of the box, all accessed methods are const
+    NSMountLogic m_NSMountLogic;// is okay, used only on policy update
+    // below elements are set once and not changed, can be read from many threads
     PrepareAppFlags m_prepareAppFlags;
     Offline m_offline;
 };
index f2eea2e92d0845fda7f06663d51f8bfc8485bc06..31d4544a6b82f257a3cb0cb0d30821a4b9ea9e74 100644 (file)
@@ -101,8 +101,9 @@ auto prepare(DB::SqlConnection &db, const char *fmt) {
 
 /* Common code for handling SqlConnection exceptions */
 template <class F>
-auto try_catch_db(F &&f) {
+auto try_catch_db(std::mutex &m, F &&f) {
     try {
+        std::lock_guard<std::mutex> lock(m);
         return std::forward<F>(f)();
     } catch (DB::SqlConnection::Exception::SyntaxError &e) {
         LogError("Syntax error in command: " << e.DumpToString());
@@ -189,28 +190,28 @@ PrivilegeDb::StatementWrapper PrivilegeDb::getStatement(StmtType queryType)
 
 void PrivilegeDb::BeginTransaction(void)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         mSqlConnection.BeginTransaction();
     });
 }
 
 void PrivilegeDb::CommitTransaction(void)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         mSqlConnection.CommitTransaction();
     });
 }
 
 void PrivilegeDb::RollbackTransaction(void)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         mSqlConnection.RollbackTransaction();
     });
 }
 
 bool PrivilegeDb::PkgNameExists(const std::string &pkgName)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EPkgNameExists);
         int cnt = 0;
 
@@ -226,7 +227,7 @@ bool PrivilegeDb::PkgNameExists(const std::string &pkgName)
 
 bool PrivilegeDb::AppNameExists(const std::string &appName)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EAppNameExists);
         int cnt = 0;
 
@@ -242,7 +243,7 @@ bool PrivilegeDb::AppNameExists(const std::string &appName)
 
 void PrivilegeDb::GetAppPkgName(const std::string &appName, std::string &pkgName)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         pkgName.clear();
 
         auto command = getStatement(StmtType::EGetAppPkgName);
@@ -255,7 +256,7 @@ void PrivilegeDb::GetAppPkgName(const std::string &appName, std::string &pkgName
 
 bool PrivilegeDb::GetAppPkgInfo(const std::string &appName, std::string &pkgName, bool &isHybrid, bool &isSharedRO)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetAppPkgInfo);
         command->BindString(1, appName);
 
@@ -271,7 +272,7 @@ bool PrivilegeDb::GetAppPkgInfo(const std::string &appName, std::string &pkgName
 
 void PrivilegeDb::GetAppVersion(const std::string &appName, std::string &tizenVer)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         tizenVer.clear();
 
         auto command = getStatement(StmtType::EGetAppVersion);
@@ -309,7 +310,7 @@ void PrivilegeDb::AddApplication(
         const std::string &authorName,
         bool isHybrid)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EAddApplication);
         command->BindString(1, appName);
         command->BindString(2, pkgName);
@@ -334,16 +335,15 @@ void PrivilegeDb::RemoveApplication(
         bool &pkgNameIsNoMore,
         bool &authorNameIsNoMore)
 {
-    try_catch_db([&] {
-        if (!AppNameExists(appName))
-            return;
+    if (!AppNameExists(appName))
+        return;
+    std::string pkgName;
+    GetAppPkgName(appName, pkgName);
 
-        std::string pkgName;
-        GetAppPkgName(appName, pkgName);
-
-        std::string authorHash;
-        GetPkgAuthorHash(pkgName, authorHash);
+    std::string authorHash;
+    GetPkgAuthorHash(pkgName, authorHash);
 
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ERemoveApplication);
         command->BindString(1, appName);
         command->BindInteger(2, static_cast<unsigned int>(uid));
@@ -354,16 +354,16 @@ void PrivilegeDb::RemoveApplication(
         };
 
         LogDebug("Removed appName: " << appName);
-
-        appNameIsNoMore = !(AppNameExists(appName));
-        pkgNameIsNoMore = !(PkgNameExists(pkgName));
-        authorNameIsNoMore = !(AuthorExists(authorHash));
     });
+
+    appNameIsNoMore = !(AppNameExists(appName));
+    pkgNameIsNoMore = !(PkgNameExists(pkgName));
+    authorNameIsNoMore = !(AuthorExists(authorHash));
 }
 
 void PrivilegeDb::GetPathSharingCount(const std::string &path, int &count)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetPathSharedCount);
         command->BindString(1, path);
 
@@ -375,7 +375,7 @@ void PrivilegeDb::GetPathSharingCount(const std::string &path, int &count)
 void PrivilegeDb::GetOwnerTargetSharingCount(const std::string &ownerAppName,
     const std::string &targetAppName, int &count)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetOwnerTargetSharedCount);
         command->BindString(1, ownerAppName);
         command->BindString(2, targetAppName);
@@ -388,7 +388,7 @@ void PrivilegeDb::GetOwnerTargetSharingCount(const std::string &ownerAppName,
 void PrivilegeDb::GetTargetPathSharingCount(const std::string &targetAppName,
     const std::string &path, int &count)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetTargetPathSharedCount);
         command->BindString(1, targetAppName);
         command->BindString(2, path);
@@ -402,7 +402,7 @@ void PrivilegeDb::ApplyPrivateSharing(const std::string &ownerAppName,
     const std::string &targetAppName, const std::string &path,
     const std::string &pathLabel)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EAddPrivatePathSharing);
         command->BindString(1, ownerAppName);
         command->BindString(2, targetAppName);
@@ -416,7 +416,7 @@ void PrivilegeDb::ApplyPrivateSharing(const std::string &ownerAppName,
 void PrivilegeDb::DropPrivateSharing(const std::string &ownerAppName,
     const std::string &targetAppName, const std::string &path)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ERemovePrivatePathSharing);
         command->BindString(1, ownerAppName);
         command->BindString(2, targetAppName);
@@ -427,7 +427,7 @@ void PrivilegeDb::DropPrivateSharing(const std::string &ownerAppName,
 }
 
 void PrivilegeDb::GetAllPrivateSharing(std::map<std::string, std::vector<std::string>> &appPathMap) {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetAllSharedPaths);
         while (command->Step()) {
             std::string appName = command->GetColumnString(0);
@@ -441,7 +441,7 @@ void PrivilegeDb::GetAllPrivateSharing(std::map<std::string, std::vector<std::st
 void PrivilegeDb::GetPrivateSharingForOwner(const std::string &ownerAppName,
                                             std::map<std::string, std::vector<std::string>> &ownerSharing)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetSharingForOwner);
         command->BindString(1, ownerAppName);
         while (command->Step()) {
@@ -456,7 +456,7 @@ void PrivilegeDb::GetPrivateSharingForOwner(const std::string &ownerAppName,
 void PrivilegeDb::GetPrivateSharingForTarget(const std::string &targetAppName,
                                              std::map<std::string, std::vector<std::string>> &targetSharing)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetSharingForTarget);
         command->BindString(1, targetAppName);
         while (command->Step()) {
@@ -469,7 +469,7 @@ void PrivilegeDb::GetPrivateSharingForTarget(const std::string &targetAppName,
 }
 
 void PrivilegeDb::SquashSharing(const std::string &targetAppName, const std::string &path) {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ESquashSharing);
         command->BindString(1, targetAppName);
         command->BindString(2, path);
@@ -479,7 +479,7 @@ void PrivilegeDb::SquashSharing(const std::string &targetAppName, const std::str
 }
 
 void PrivilegeDb::ClearPrivateSharing() {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         {
             auto command = getStatement(StmtType::EClearSharing);
             command->Step();
@@ -493,7 +493,7 @@ void PrivilegeDb::ClearPrivateSharing() {
 
 void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetUserApps);
         command->BindInteger(1, static_cast<unsigned int>(uid));
         apps.clear();
@@ -507,7 +507,7 @@ void PrivilegeDb::GetUserApps(uid_t uid, std::vector<std::string> &apps)
 
 void PrivilegeDb::GetUserAppsFromPkg(uid_t uid, const std::string &pkgName, std::vector<std::string> &apps)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetUserAppsFromPkg);
         command->BindInteger(1, static_cast<unsigned int>(uid));
         command->BindString(2, pkgName);
@@ -522,7 +522,7 @@ void PrivilegeDb::GetUserAppsFromPkg(uid_t uid, const std::string &pkgName, std:
 
 void PrivilegeDb::GetUserPkgs(uid_t uid, std::vector<std::string> &pkgs)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetUserPkgs);
         command->BindInteger(1, static_cast<unsigned int>(uid));
         pkgs.clear();
@@ -536,7 +536,7 @@ void PrivilegeDb::GetUserPkgs(uid_t uid, std::vector<std::string> &pkgs)
 
 void PrivilegeDb::GetAllPackages(std::vector<std::string> &packages)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetAllPackages);
         packages.clear();
         while (command->Step()) {
@@ -550,7 +550,7 @@ void PrivilegeDb::GetAllPackages(std::vector<std::string> &packages)
 void PrivilegeDb::GetPkgApps(const std::string &pkgName,
         std::vector<std::string> &appNames)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetAppsInPkg);
 
         command->BindString(1, pkgName);
@@ -566,7 +566,7 @@ void PrivilegeDb::GetPkgApps(const std::string &pkgName,
 
 void PrivilegeDb::GetPkgAuthorHash(const std::string &pkgName, std::string &authorHash)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetPkgAuthor);
 
         command->BindString(1, pkgName);
@@ -582,7 +582,7 @@ void PrivilegeDb::GetPkgAuthorHash(const std::string &pkgName, std::string &auth
 
 bool PrivilegeDb::AuthorExists(const std::string &authorHash)
 {
-    return try_catch_db([&]() -> bool {
+    return try_catch_db(m_api_mutex, [&]() -> bool {
         auto command = getStatement(StmtType::EAuthorExists);
         int cnt = 0;
 
@@ -598,7 +598,7 @@ bool PrivilegeDb::AuthorExists(const std::string &authorHash)
 
 void PrivilegeDb::GetGroupsRelatedPrivileges(std::vector<std::pair<std::string, std::string>> &privileges)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EGetGroupsRelatedPrivileges);
 
         while (command->Step()) {
@@ -612,7 +612,7 @@ void PrivilegeDb::GetGroupsRelatedPrivileges(std::vector<std::pair<std::string,
 
 void PrivilegeDb::SetSharedROPackage(const std::string &pkgName, bool isSharedRO)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ESetPackageSharedRO);
         command->BindInteger(1, isSharedRO);
         command->BindString(2, pkgName);
@@ -624,7 +624,7 @@ void PrivilegeDb::SetSharedROPackage(const std::string &pkgName, bool isSharedRO
 
 bool PrivilegeDb::IsPackageHybrid(const std::string& pkgName)
 {
-    return try_catch_db([&]() -> bool {
+    return try_catch_db(m_api_mutex, [&]() -> bool {
         auto command = getStatement(StmtType::EIsPackageHybrid);
         command->BindString(1, pkgName);
         int isHybrid = 0;
@@ -641,7 +641,7 @@ bool PrivilegeDb::IsPackageHybrid(const std::string& pkgName)
 void PrivilegeDb::AddAppDefinedPrivilege(const std::string &appName, uid_t uid,
                                          const AppDefinedPrivilege &privilege)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EAddAppDefinedPrivilege);
         command->BindString(1, appName);
         command->BindInteger(2, uid);
@@ -669,7 +669,7 @@ void PrivilegeDb::AddAppDefinedPrivileges(const std::string &appName, uid_t uid,
 void PrivilegeDb::AddClientPrivilege(const std::string &appName, uid_t uid, const std::string &privilege,
                                      const std::string &license)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::EAddClientPrivilege);
         command->BindString(1, appName);
         command->BindInteger(2, uid);
@@ -688,7 +688,7 @@ void PrivilegeDb::AddClientPrivilege(const std::string &appName, uid_t uid, cons
 
 void PrivilegeDb::RemoveAppDefinedPrivileges(const std::string &appName, uid_t uid)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ERemoveAppDefinedPrivileges);
         command->BindString(1, appName);
         command->BindInteger(2, uid);
@@ -704,7 +704,7 @@ void PrivilegeDb::RemoveAppDefinedPrivileges(const std::string &appName, uid_t u
 
 void PrivilegeDb::RemoveClientPrivileges(const std::string &appName, uid_t uid)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         auto command = getStatement(StmtType::ERemoveClientPrivileges);
         command->BindString(1, appName);
         command->BindInteger(2, uid);
@@ -721,7 +721,7 @@ void PrivilegeDb::RemoveClientPrivileges(const std::string &appName, uid_t uid)
 void PrivilegeDb::GetAppDefinedPrivileges(const std::string &appName, uid_t uid,
                                           AppDefinedPrivilegesVector &privileges)
 {
-    try_catch_db([&] {
+    try_catch_db(m_api_mutex, [&] {
         privileges.clear();
 
         auto command = getStatement(StmtType::EGetAppDefinedPrivileges);
@@ -744,7 +744,7 @@ bool PrivilegeDb::GetAppPkgLicenseForAppDefinedPrivilege(
         std::string &pkgName,
         std::string &license)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         appName.clear();
         pkgName.clear();
         license.clear();
@@ -772,7 +772,7 @@ bool PrivilegeDb::GetLicenseForClientPrivilegeAndApp(
         const std::string &privilege,
         std::string &license)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         license.clear();
 
         auto command = getStatement(StmtType::EGetLicenseForClientPrivilegeAndApp);
@@ -799,7 +799,7 @@ bool PrivilegeDb::GetLicenseForClientPrivilegeAndPkg(
         const std::string &privilege,
         std::string &license)
 {
-    return try_catch_db([&] {
+    return try_catch_db(m_api_mutex, [&] {
         license.clear();
 
         auto command = getStatement(StmtType::EGetLicenseForClientPrivilegeAndPkg);
@@ -822,7 +822,7 @@ bool PrivilegeDb::GetLicenseForClientPrivilegeAndPkg(
 
 bool PrivilegeDb::IsUserPkgInstalled(const std::string& pkgName, uid_t uid)
 {
-    return try_catch_db([&]() -> bool {
+    return try_catch_db(m_api_mutex, [&]() -> bool {
         auto command = getStatement(StmtType::EIsUserPkgInstalled);
         command->BindString(1, pkgName);
         command->BindInteger(2, uid);