PlatformResult CheckAccess(const std::vector<std::string>& privileges) {
LoggerD("Enter");
+ // Local cache of mapped privilege strings. This routine can be called many times, especially
+ // during application launch, generating a high overhead of retrieving mapped privileges from
+ // the underlying databases. This is especially the case since the same mappings can end up
+ // being retrieved several times.
+ using MappedPrivilegeCache = std::map<std::string, std::vector<std::string>>;
+ static MappedPrivilegeCache mapped_privilege_cache;
+
std::string api_version;
PlatformResult res = common::tools::GetPkgApiVersion(&api_version);
if (res.IsError()) {
g_list_free(mapped_glist);
};
- input_glist = g_list_append(input_glist, (void*)input_priv.c_str());
- int ret = privilege_manager_get_mapped_privilege_list(api_version.c_str(),
- PRVMGR_PACKAGE_TYPE_WRT,
- input_glist,
- &mapped_glist);
- if (ret != PRVMGR_ERR_NONE) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get mapped privilege list");
- }
-
- LoggerD("Mapped privileges:");
- std::vector<std::string> mapped_vector;
- auto push_elem = [](gpointer data, gpointer user_data) -> void {
- if (data && user_data) {
- std::vector<std::string>* mapped_vector =
- static_cast<std::vector<std::string>*>(user_data);
- char* char_data = static_cast<char*>(data);
- mapped_vector->push_back(char_data);
- LoggerD("mapped to: %s", char_data);
+ std::vector<std::string>* mapped_vector_ptr = nullptr;
+
+ // Check if mapped privilege is in local cache first
+ MappedPrivilegeCache::const_iterator it = mapped_privilege_cache.find(input_priv);
+ if (mapped_privilege_cache.end() == it) {
+ LoggerD("Mapped privileges - need to be fetched from database");
+ // Not in cache - retrieve from underlying databases.
+ input_glist = g_list_append(input_glist, (void*)input_priv.c_str());
+ int ret = privilege_manager_get_mapped_privilege_list(api_version.c_str(),
+ PRVMGR_PACKAGE_TYPE_WRT,
+ input_glist,
+ &mapped_glist);
+ if (PRVMGR_ERR_NONE != ret) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get mapped privilege list");
}
- };
- g_list_foreach (mapped_glist, push_elem, &mapped_vector);
- if (!AccessControl::GetInstance().CheckAccess(mapped_vector)){
- for (const auto& mapped_priv : mapped_vector) {
+ // initialize empty cache vector
+ mapped_privilege_cache[input_priv] = std::vector<std::string>();
+ LoggerD("Mapped privileges:");
+ auto push_elem = [](gpointer data, gpointer user_data) -> void {
+ if (data && user_data) {
+ std::vector<std::string>* mapped_vector =
+ static_cast<std::vector<std::string>*>(user_data);
+ char* char_data = static_cast<char*>(data);
+ mapped_vector->push_back(char_data);
+ LoggerD("mapped to: %s", char_data);
+ }
+ };
+ // fill the vector with data
+ g_list_foreach (mapped_glist, push_elem, &mapped_privilege_cache[input_priv]);
+ mapped_vector_ptr = &mapped_privilege_cache[input_priv];
+ } else {
+ // Retrieve from local cache
+ LoggerD("Mapped privileges already in cache");
+ mapped_vector_ptr = (std::vector<std::string>*) &(it->second);
+ }
+
+ if (!AccessControl::GetInstance().CheckAccess(*mapped_vector_ptr)){
+ for (const auto& mapped_priv : *mapped_vector_ptr) {
LoggerD("Access to privilege: %s has been denied.", mapped_priv.c_str());
}
return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied");
PlatformResult GetPkgApiVersion(std::string* api_version) {
LoggerD("Entered");
+ // Local cache of API version string. This can be expensive to retrieve from
+ // underlying databases and this routine can be called many times during
+ // application launch.
+ static std::string cached_api_version;
+ static int cached_pid = -1;
+
char* app_id = nullptr;
char* pkgid = nullptr;
char* api_ver = nullptr;
};
pid_t pid = getpid();
- int ret = app_manager_get_app_id(pid, &app_id);
- if (ret != APP_MANAGER_ERROR_NONE) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get app id");
- }
+ if (cached_pid == pid) {
+ *api_version = cached_api_version; // Retrieve from local cache
+ } else {
+ int ret = app_manager_get_app_id(pid, &app_id);
+ if (ret != APP_MANAGER_ERROR_NONE) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get app id");
+ }
- ret = app_info_create(app_id, &app_handle);
- if (ret != APP_MANAGER_ERROR_NONE) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get app info");
- }
+ ret = app_info_create(app_id, &app_handle);
+ if (ret != APP_MANAGER_ERROR_NONE) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get app info");
+ }
- ret = app_info_get_package(app_handle, &pkgid);
- if ((ret != APP_MANAGER_ERROR_NONE) || (pkgid == nullptr)) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkg id");
- }
+ ret = app_info_get_package(app_handle, &pkgid);
+ if ((ret != APP_MANAGER_ERROR_NONE) || (pkgid == nullptr)) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkg id");
+ }
- ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, getuid(), &pkginfo_handle);
- if (ret != PMINFO_R_OK) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkginfo_h");
- }
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, getuid(), &pkginfo_handle);
+ if (ret != PMINFO_R_OK) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkginfo_h");
+ }
+
+ ret = pkgmgrinfo_pkginfo_get_api_version(pkginfo_handle, &api_ver);
+ if (ret != PMINFO_R_OK) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get api version");
+ }
+
+ cached_api_version = api_ver; // Save in local cache
+ cached_pid = pid;
- ret = pkgmgrinfo_pkginfo_get_api_version(pkginfo_handle, &api_ver);
- if (ret != PMINFO_R_OK) {
- return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Fail to get api version");
+ *api_version = api_ver;
}
- *api_version = api_ver;
return PlatformResult(ErrorCode::NO_ERROR);
}